2005-08-10 02:30:24 +00:00
|
|
|
/* Netfilter messages via netlink socket. Allows for user space
|
|
|
|
* protocol helpers and general trouble making from userspace.
|
|
|
|
*
|
|
|
|
* (C) 2001 by Jay Schulist <jschlst@samba.org>,
|
|
|
|
* (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
|
2017-02-10 11:08:17 +00:00
|
|
|
* (C) 2005-2017 by Pablo Neira Ayuso <pablo@netfilter.org>
|
2005-08-10 02:30:24 +00:00
|
|
|
*
|
|
|
|
* Initial netfilter messages via netlink development funded and
|
|
|
|
* generally made possible by Network Robots, Inc. (www.networkrobots.com)
|
|
|
|
*
|
|
|
|
* Further development of this code funded by Astaro AG (http://www.astaro.com)
|
|
|
|
*
|
|
|
|
* This software may be used and distributed according to the terms
|
|
|
|
* of the GNU General Public License, incorporated herein by reference.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/socket.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/sockios.h>
|
|
|
|
#include <linux/net.h>
|
|
|
|
#include <linux/skbuff.h>
|
2016-12-24 19:46:01 +00:00
|
|
|
#include <linux/uaccess.h>
|
2005-08-10 02:30:24 +00:00
|
|
|
#include <net/sock.h>
|
|
|
|
#include <linux/init.h>
|
2018-05-27 09:24:34 +00:00
|
|
|
#include <linux/sched/signal.h>
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2013-03-27 06:47:04 +00:00
|
|
|
#include <net/netlink.h>
|
2021-04-01 14:11:05 +00:00
|
|
|
#include <net/netns/generic.h>
|
2023-02-20 16:24:00 +00:00
|
|
|
#include <linux/netfilter.h>
|
2005-08-10 02:30:24 +00:00
|
|
|
#include <linux/netfilter/nfnetlink.h>
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
2005-08-10 02:40:55 +00:00
|
|
|
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
|
|
|
|
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
|
2020-06-21 05:27:36 +00:00
|
|
|
MODULE_DESCRIPTION("Netfilter messages via netlink socket");
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2015-12-03 09:49:42 +00:00
|
|
|
#define nfnl_dereference_protected(id) \
|
|
|
|
rcu_dereference_protected(table[(id)].subsys, \
|
|
|
|
lockdep_nfnl_is_held((id)))
|
|
|
|
|
2018-05-30 19:17:56 +00:00
|
|
|
#define NFNL_MAX_ATTR_COUNT 32
|
|
|
|
|
2021-04-01 14:11:05 +00:00
|
|
|
static unsigned int nfnetlink_pernet_id __read_mostly;
|
|
|
|
|
2022-08-05 08:59:57 +00:00
|
|
|
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
|
|
|
static DEFINE_SPINLOCK(nfnl_grp_active_lock);
|
|
|
|
#endif
|
|
|
|
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net {
|
|
|
|
struct sock *nfnl;
|
|
|
|
};
|
|
|
|
|
2013-02-05 00:50:26 +00:00
|
|
|
static struct {
|
|
|
|
struct mutex mutex;
|
|
|
|
const struct nfnetlink_subsystem __rcu *subsys;
|
|
|
|
} table[NFNL_SUBSYS_COUNT];
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2020-10-02 11:51:29 +00:00
|
|
|
static struct lock_class_key nfnl_lockdep_keys[NFNL_SUBSYS_COUNT];
|
|
|
|
|
|
|
|
static const char *const nfnl_lockdep_names[NFNL_SUBSYS_COUNT] = {
|
|
|
|
[NFNL_SUBSYS_NONE] = "nfnl_subsys_none",
|
|
|
|
[NFNL_SUBSYS_CTNETLINK] = "nfnl_subsys_ctnetlink",
|
|
|
|
[NFNL_SUBSYS_CTNETLINK_EXP] = "nfnl_subsys_ctnetlink_exp",
|
|
|
|
[NFNL_SUBSYS_QUEUE] = "nfnl_subsys_queue",
|
|
|
|
[NFNL_SUBSYS_ULOG] = "nfnl_subsys_ulog",
|
|
|
|
[NFNL_SUBSYS_OSF] = "nfnl_subsys_osf",
|
|
|
|
[NFNL_SUBSYS_IPSET] = "nfnl_subsys_ipset",
|
|
|
|
[NFNL_SUBSYS_ACCT] = "nfnl_subsys_acct",
|
|
|
|
[NFNL_SUBSYS_CTNETLINK_TIMEOUT] = "nfnl_subsys_cttimeout",
|
|
|
|
[NFNL_SUBSYS_CTHELPER] = "nfnl_subsys_cthelper",
|
|
|
|
[NFNL_SUBSYS_NFTABLES] = "nfnl_subsys_nftables",
|
|
|
|
[NFNL_SUBSYS_NFT_COMPAT] = "nfnl_subsys_nftcompat",
|
2021-06-04 10:27:07 +00:00
|
|
|
[NFNL_SUBSYS_HOOK] = "nfnl_subsys_hook",
|
2020-10-02 11:51:29 +00:00
|
|
|
};
|
|
|
|
|
2012-06-29 06:15:22 +00:00
|
|
|
static const int nfnl_group2type[NFNLGRP_MAX+1] = {
|
|
|
|
[NFNLGRP_CONNTRACK_NEW] = NFNL_SUBSYS_CTNETLINK,
|
|
|
|
[NFNLGRP_CONNTRACK_UPDATE] = NFNL_SUBSYS_CTNETLINK,
|
|
|
|
[NFNLGRP_CONNTRACK_DESTROY] = NFNL_SUBSYS_CTNETLINK,
|
|
|
|
[NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP,
|
|
|
|
[NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP,
|
|
|
|
[NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
|
2014-11-14 17:14:33 +00:00
|
|
|
[NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES,
|
|
|
|
[NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT,
|
2015-11-28 20:53:04 +00:00
|
|
|
[NFNLGRP_NFTRACE] = NFNL_SUBSYS_NFTABLES,
|
2012-06-29 06:15:22 +00:00
|
|
|
};
|
|
|
|
|
2021-04-01 14:11:05 +00:00
|
|
|
static struct nfnl_net *nfnl_pernet(struct net *net)
|
|
|
|
{
|
|
|
|
return net_generic(net, nfnetlink_pernet_id);
|
|
|
|
}
|
|
|
|
|
2013-02-05 00:50:26 +00:00
|
|
|
void nfnl_lock(__u8 subsys_id)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2013-02-05 00:50:26 +00:00
|
|
|
mutex_lock(&table[subsys_id].mutex);
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
2008-10-14 18:58:31 +00:00
|
|
|
EXPORT_SYMBOL_GPL(nfnl_lock);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2013-02-05 00:50:26 +00:00
|
|
|
void nfnl_unlock(__u8 subsys_id)
|
2007-03-14 23:39:25 +00:00
|
|
|
{
|
2013-02-05 00:50:26 +00:00
|
|
|
mutex_unlock(&table[subsys_id].mutex);
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
2008-10-14 18:58:31 +00:00
|
|
|
EXPORT_SYMBOL_GPL(nfnl_unlock);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2014-02-18 18:06:48 +00:00
|
|
|
#ifdef CONFIG_PROVE_LOCKING
|
2015-10-08 13:28:56 +00:00
|
|
|
bool lockdep_nfnl_is_held(u8 subsys_id)
|
2014-02-18 18:06:48 +00:00
|
|
|
{
|
|
|
|
return lockdep_is_held(&table[subsys_id].mutex);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(lockdep_nfnl_is_held);
|
|
|
|
#endif
|
|
|
|
|
2007-09-28 21:15:45 +00:00
|
|
|
int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2018-05-30 19:17:56 +00:00
|
|
|
u8 cb_id;
|
|
|
|
|
|
|
|
/* Sanity-check attr_count size to avoid stack buffer overflow. */
|
|
|
|
for (cb_id = 0; cb_id < n->cb_count; cb_id++)
|
|
|
|
if (WARN_ON(n->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2013-02-05 00:50:26 +00:00
|
|
|
nfnl_lock(n->subsys_id);
|
|
|
|
if (table[n->subsys_id].subsys) {
|
|
|
|
nfnl_unlock(n->subsys_id);
|
2005-08-10 02:43:44 +00:00
|
|
|
return -EBUSY;
|
|
|
|
}
|
2013-02-05 00:50:26 +00:00
|
|
|
rcu_assign_pointer(table[n->subsys_id].subsys, n);
|
|
|
|
nfnl_unlock(n->subsys_id);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2007-03-14 23:42:11 +00:00
|
|
|
EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2007-09-28 21:15:45 +00:00
|
|
|
int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2013-02-05 00:50:26 +00:00
|
|
|
nfnl_lock(n->subsys_id);
|
|
|
|
table[n->subsys_id].subsys = NULL;
|
|
|
|
nfnl_unlock(n->subsys_id);
|
2011-07-18 14:08:07 +00:00
|
|
|
synchronize_rcu();
|
2005-08-10 02:30:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-03-14 23:42:11 +00:00
|
|
|
EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2017-02-10 11:08:08 +00:00
|
|
|
static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u16 type)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2017-02-10 11:08:08 +00:00
|
|
|
u8 subsys_id = NFNL_SUBSYS_ID(type);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2007-03-14 23:41:28 +00:00
|
|
|
if (subsys_id >= NFNL_SUBSYS_COUNT)
|
2005-08-10 02:30:24 +00:00
|
|
|
return NULL;
|
|
|
|
|
2013-02-05 00:50:26 +00:00
|
|
|
return rcu_dereference(table[subsys_id].subsys);
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
|
|
|
|
2007-09-28 21:15:45 +00:00
|
|
|
static inline const struct nfnl_callback *
|
2017-02-10 11:08:08 +00:00
|
|
|
nfnetlink_find_client(u16 type, const struct nfnetlink_subsystem *ss)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2017-02-10 11:08:08 +00:00
|
|
|
u8 cb_id = NFNL_MSG_TYPE(type);
|
2007-02-12 19:15:49 +00:00
|
|
|
|
2007-03-14 23:40:38 +00:00
|
|
|
if (cb_id >= ss->cb_count)
|
2005-08-10 02:30:24 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return &ss->cb[cb_id];
|
|
|
|
}
|
|
|
|
|
2010-01-13 15:02:14 +00:00
|
|
|
int nfnetlink_has_listeners(struct net *net, unsigned int group)
|
2006-03-21 02:03:59 +00:00
|
|
|
{
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
|
|
|
|
|
|
|
return netlink_has_listeners(nfnlnet->nfnl, group);
|
2006-03-21 02:03:59 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
|
|
|
|
|
2013-04-17 06:47:08 +00:00
|
|
|
int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid,
|
2012-04-15 05:58:06 +00:00
|
|
|
unsigned int group, int echo, gfp_t flags)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
|
|
|
|
|
|
|
return nlmsg_notify(nfnlnet->nfnl, skb, portid, group, echo, flags);
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
2007-03-14 23:42:11 +00:00
|
|
|
EXPORT_SYMBOL_GPL(nfnetlink_send);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2013-04-17 06:47:08 +00:00
|
|
|
int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error)
|
2009-03-23 12:21:06 +00:00
|
|
|
{
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
|
|
|
|
|
|
|
return netlink_set_err(nfnlnet->nfnl, portid, group, error);
|
2009-03-23 12:21:06 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfnetlink_set_err);
|
|
|
|
|
2020-08-23 11:55:36 +00:00
|
|
|
int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
2020-08-23 11:55:36 +00:00
|
|
|
int err;
|
|
|
|
|
2021-04-01 14:11:05 +00:00
|
|
|
err = nlmsg_unicast(nfnlnet->nfnl, skb, portid);
|
2020-08-23 11:55:36 +00:00
|
|
|
if (err == -EAGAIN)
|
|
|
|
err = -ENOBUFS;
|
|
|
|
|
|
|
|
return err;
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
2007-03-14 23:42:11 +00:00
|
|
|
EXPORT_SYMBOL_GPL(nfnetlink_unicast);
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2021-04-01 14:11:04 +00:00
|
|
|
void nfnetlink_broadcast(struct net *net, struct sk_buff *skb, __u32 portid,
|
|
|
|
__u32 group, gfp_t allocation)
|
|
|
|
{
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
|
|
|
|
|
|
|
netlink_broadcast(nfnlnet->nfnl, skb, portid, group, allocation);
|
2021-04-01 14:11:04 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(nfnetlink_broadcast);
|
|
|
|
|
2005-08-10 02:30:24 +00:00
|
|
|
/* Process one complete nfnetlink message. */
|
2017-04-12 12:34:04 +00:00
|
|
|
static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
|
|
struct netlink_ext_ack *extack)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2010-01-13 15:02:14 +00:00
|
|
|
struct net *net = sock_net(skb->sk);
|
2007-09-28 21:15:45 +00:00
|
|
|
const struct nfnl_callback *nc;
|
|
|
|
const struct nfnetlink_subsystem *ss;
|
2007-03-23 06:30:12 +00:00
|
|
|
int type, err;
|
2005-08-10 02:30:24 +00:00
|
|
|
|
|
|
|
/* All the messages must at least contain nfgenmsg */
|
2013-03-27 06:47:04 +00:00
|
|
|
if (nlmsg_len(nlh) < sizeof(struct nfgenmsg))
|
2005-08-10 02:30:24 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
type = nlh->nlmsg_type;
|
2008-10-14 18:58:31 +00:00
|
|
|
replay:
|
2011-07-18 14:08:07 +00:00
|
|
|
rcu_read_lock();
|
2021-04-01 14:11:05 +00:00
|
|
|
|
2005-08-10 02:30:24 +00:00
|
|
|
ss = nfnetlink_get_subsys(type);
|
2005-08-10 02:43:44 +00:00
|
|
|
if (!ss) {
|
2008-10-16 22:24:51 +00:00
|
|
|
#ifdef CONFIG_MODULES
|
2011-07-18 14:08:07 +00:00
|
|
|
rcu_read_unlock();
|
2005-11-14 23:24:59 +00:00
|
|
|
request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
|
2011-07-18 14:08:07 +00:00
|
|
|
rcu_read_lock();
|
2005-11-14 23:24:59 +00:00
|
|
|
ss = nfnetlink_get_subsys(type);
|
2005-08-10 02:43:44 +00:00
|
|
|
if (!ss)
|
|
|
|
#endif
|
2011-07-18 14:08:07 +00:00
|
|
|
{
|
|
|
|
rcu_read_unlock();
|
2007-03-23 06:30:12 +00:00
|
|
|
return -EINVAL;
|
2011-07-18 14:08:07 +00:00
|
|
|
}
|
2005-08-10 02:43:44 +00:00
|
|
|
}
|
2005-08-10 02:30:24 +00:00
|
|
|
|
|
|
|
nc = nfnetlink_find_client(type, ss);
|
2011-07-18 14:08:07 +00:00
|
|
|
if (!nc) {
|
|
|
|
rcu_read_unlock();
|
2007-03-23 06:30:12 +00:00
|
|
|
return -EINVAL;
|
2011-07-18 14:08:07 +00:00
|
|
|
}
|
2005-08-10 02:30:24 +00:00
|
|
|
|
|
|
|
{
|
2013-03-27 06:47:04 +00:00
|
|
|
int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
2017-02-10 11:08:08 +00:00
|
|
|
u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
|
2018-05-30 19:17:56 +00:00
|
|
|
struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
|
2009-06-02 18:03:33 +00:00
|
|
|
struct nlattr *attr = (void *)nlh + min_len;
|
|
|
|
int attrlen = nlh->nlmsg_len - min_len;
|
2013-02-05 00:50:26 +00:00
|
|
|
__u8 subsys_id = NFNL_SUBSYS_ID(type);
|
2021-04-22 22:17:09 +00:00
|
|
|
struct nfnl_info info = {
|
|
|
|
.net = net,
|
|
|
|
.sk = nfnlnet->nfnl,
|
|
|
|
.nlh = nlh,
|
2021-05-30 22:08:09 +00:00
|
|
|
.nfmsg = nlmsg_data(nlh),
|
2021-04-22 22:17:09 +00:00
|
|
|
.extack = extack,
|
|
|
|
};
|
2009-06-02 18:03:33 +00:00
|
|
|
|
2018-05-30 19:17:56 +00:00
|
|
|
/* Sanity-check NFNL_MAX_ATTR_COUNT */
|
|
|
|
if (ss->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT) {
|
|
|
|
rcu_read_unlock();
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
netlink: make validation more configurable for future strictness
We currently have two levels of strict validation:
1) liberal (default)
- undefined (type >= max) & NLA_UNSPEC attributes accepted
- attribute length >= expected accepted
- garbage at end of message accepted
2) strict (opt-in)
- NLA_UNSPEC attributes accepted
- attribute length >= expected accepted
Split out parsing strictness into four different options:
* TRAILING - check that there's no trailing data after parsing
attributes (in message or nested)
* MAXTYPE - reject attrs > max known type
* UNSPEC - reject attributes with NLA_UNSPEC policy entries
* STRICT_ATTRS - strictly validate attribute size
The default for future things should be *everything*.
The current *_strict() is a combination of TRAILING and MAXTYPE,
and is renamed to _deprecated_strict().
The current regular parsing has none of this, and is renamed to
*_parse_deprecated().
Additionally it allows us to selectively set one of the new flags
even on old policies. Notably, the UNSPEC flag could be useful in
this case, since it can be arranged (by filling in the policy) to
not be an incompatible userspace ABI change, but would then going
forward prevent forgetting attribute entries. Similar can apply
to the POLICY flag.
We end up with the following renames:
* nla_parse -> nla_parse_deprecated
* nla_parse_strict -> nla_parse_deprecated_strict
* nlmsg_parse -> nlmsg_parse_deprecated
* nlmsg_parse_strict -> nlmsg_parse_deprecated_strict
* nla_parse_nested -> nla_parse_nested_deprecated
* nla_validate_nested -> nla_validate_nested_deprecated
Using spatch, of course:
@@
expression TB, MAX, HEAD, LEN, POL, EXT;
@@
-nla_parse(TB, MAX, HEAD, LEN, POL, EXT)
+nla_parse_deprecated(TB, MAX, HEAD, LEN, POL, EXT)
@@
expression NLH, HDRLEN, TB, MAX, POL, EXT;
@@
-nlmsg_parse(NLH, HDRLEN, TB, MAX, POL, EXT)
+nlmsg_parse_deprecated(NLH, HDRLEN, TB, MAX, POL, EXT)
@@
expression NLH, HDRLEN, TB, MAX, POL, EXT;
@@
-nlmsg_parse_strict(NLH, HDRLEN, TB, MAX, POL, EXT)
+nlmsg_parse_deprecated_strict(NLH, HDRLEN, TB, MAX, POL, EXT)
@@
expression TB, MAX, NLA, POL, EXT;
@@
-nla_parse_nested(TB, MAX, NLA, POL, EXT)
+nla_parse_nested_deprecated(TB, MAX, NLA, POL, EXT)
@@
expression START, MAX, POL, EXT;
@@
-nla_validate_nested(START, MAX, POL, EXT)
+nla_validate_nested_deprecated(START, MAX, POL, EXT)
@@
expression NLH, HDRLEN, MAX, POL, EXT;
@@
-nlmsg_validate(NLH, HDRLEN, MAX, POL, EXT)
+nlmsg_validate_deprecated(NLH, HDRLEN, MAX, POL, EXT)
For this patch, don't actually add the strict, non-renamed versions
yet so that it breaks compile if I get it wrong.
Also, while at it, make nla_validate and nla_parse go down to a
common __nla_validate_parse() function to avoid code duplication.
Ultimately, this allows us to have very strict validation for every
new caller of nla_parse()/nlmsg_parse() etc as re-introduced in the
next patch, while existing things will continue to work as is.
In effect then, this adds fully strict validation for any new command.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-04-26 12:07:28 +00:00
|
|
|
err = nla_parse_deprecated(cda, ss->cb[cb_id].attr_count,
|
|
|
|
attr, attrlen,
|
|
|
|
ss->cb[cb_id].policy, extack);
|
2012-06-28 02:57:49 +00:00
|
|
|
if (err < 0) {
|
|
|
|
rcu_read_unlock();
|
2009-06-02 18:03:33 +00:00
|
|
|
return err;
|
2012-06-28 02:57:49 +00:00
|
|
|
}
|
2007-02-12 19:15:49 +00:00
|
|
|
|
2021-04-22 22:17:12 +00:00
|
|
|
if (!nc->call) {
|
2011-07-18 14:08:07 +00:00
|
|
|
rcu_read_unlock();
|
2021-04-22 22:17:12 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (nc->type) {
|
|
|
|
case NFNL_CB_RCU:
|
|
|
|
err = nc->call(skb, &info, (const struct nlattr **)cda);
|
|
|
|
rcu_read_unlock();
|
|
|
|
break;
|
|
|
|
case NFNL_CB_MUTEX:
|
2011-07-18 14:08:07 +00:00
|
|
|
rcu_read_unlock();
|
2013-02-05 00:50:26 +00:00
|
|
|
nfnl_lock(subsys_id);
|
2015-12-03 09:49:42 +00:00
|
|
|
if (nfnl_dereference_protected(subsys_id) != ss ||
|
2021-04-22 22:17:09 +00:00
|
|
|
nfnetlink_find_client(type, ss) != nc) {
|
2022-11-03 01:12:02 +00:00
|
|
|
nfnl_unlock(subsys_id);
|
2011-07-18 14:08:07 +00:00
|
|
|
err = -EAGAIN;
|
2021-04-22 22:17:12 +00:00
|
|
|
break;
|
2021-04-22 22:17:09 +00:00
|
|
|
}
|
2021-04-22 22:17:12 +00:00
|
|
|
err = nc->call(skb, &info, (const struct nlattr **)cda);
|
2013-02-05 00:50:26 +00:00
|
|
|
nfnl_unlock(subsys_id);
|
2021-04-22 22:17:12 +00:00
|
|
|
break;
|
|
|
|
default:
|
netfilter: nfnetlink: add a missing rcu_read_unlock()
Reported by syzbot :
BUG: sleeping function called from invalid context at include/linux/sched/mm.h:201
in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 26899, name: syz-executor.5
1 lock held by syz-executor.5/26899:
#0: ffffffff8bf797a0 (rcu_read_lock){....}-{1:2}, at: nfnetlink_get_subsys net/netfilter/nfnetlink.c:148 [inline]
#0: ffffffff8bf797a0 (rcu_read_lock){....}-{1:2}, at: nfnetlink_rcv_msg+0x1da/0x1300 net/netfilter/nfnetlink.c:226
Preemption disabled at:
[<ffffffff8917799e>] preempt_schedule_irq+0x3e/0x90 kernel/sched/core.c:5533
CPU: 1 PID: 26899 Comm: syz-executor.5 Not tainted 5.12.0-next-20210504-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:79 [inline]
dump_stack+0x141/0x1d7 lib/dump_stack.c:120
___might_sleep.cold+0x1f1/0x237 kernel/sched/core.c:8338
might_alloc include/linux/sched/mm.h:201 [inline]
slab_pre_alloc_hook mm/slab.h:500 [inline]
slab_alloc_node mm/slub.c:2845 [inline]
kmem_cache_alloc_node+0x33d/0x3e0 mm/slub.c:2960
__alloc_skb+0x20b/0x340 net/core/skbuff.c:413
alloc_skb include/linux/skbuff.h:1107 [inline]
nlmsg_new include/net/netlink.h:953 [inline]
netlink_ack+0x1ed/0xaa0 net/netlink/af_netlink.c:2437
netlink_rcv_skb+0x33d/0x420 net/netlink/af_netlink.c:2508
nfnetlink_rcv+0x1ac/0x420 net/netfilter/nfnetlink.c:650
netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline]
netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338
netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927
sock_sendmsg_nosec net/socket.c:654 [inline]
sock_sendmsg+0xcf/0x120 net/socket.c:674
____sys_sendmsg+0x6e8/0x810 net/socket.c:2350
___sys_sendmsg+0xf3/0x170 net/socket.c:2404
__sys_sendmsg+0xe5/0x1b0 net/socket.c:2433
do_syscall_64+0x3a/0xb0 arch/x86/entry/common.c:47
entry_SYSCALL_64_after_hwframe+0x44/0xae
RIP: 0033:0x4665f9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fa8a03ee188 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 000000000056bf60 RCX: 00000000004665f9
RDX: 0000000000000000 RSI: 0000000020000480 RDI: 0000000000000004
RBP: 00000000004bfce1 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 000000000056bf60
R13: 00007fffe864480f R14: 00007fa8a03ee300 R15: 0000000000022000
================================================
WARNING: lock held when returning to user space!
5.12.0-next-20210504-syzkaller #0 Tainted: G W
------------------------------------------------
syz-executor.5/26899 is leaving the kernel with locks still held!
1 lock held by syz-executor.5/26899:
#0: ffffffff8bf797a0 (rcu_read_lock){....}-{1:2}, at: nfnetlink_get_subsys net/netfilter/nfnetlink.c:148 [inline]
#0: ffffffff8bf797a0 (rcu_read_lock){....}-{1:2}, at: nfnetlink_rcv_msg+0x1da/0x1300 net/netfilter/nfnetlink.c:226
------------[ cut here ]------------
WARNING: CPU: 0 PID: 26899 at kernel/rcu/tree_plugin.h:359 rcu_note_context_switch+0xfd/0x16e0 kernel/rcu/tree_plugin.h:359
Modules linked in:
CPU: 0 PID: 26899 Comm: syz-executor.5 Tainted: G W 5.12.0-next-20210504-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
RIP: 0010:rcu_note_context_switch+0xfd/0x16e0 kernel/rcu/tree_plugin.h:359
Code: 48 89 fa 48 c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 2e 0d 00 00 8b bd cc 03 00 00 85 ff 7e 02 <0f> 0b 65 48 8b 2c 25 00 f0 01 00 48 8d bd cc 03 00 00 48 b8 00 00
RSP: 0000:ffffc90002fffdb0 EFLAGS: 00010002
RAX: 0000000000000007 RBX: ffff8880b9c36080 RCX: ffffffff8dc99bac
RDX: 0000000000000000 RSI: 0000000000000008 RDI: 0000000000000001
RBP: ffff88808b9d1c80 R08: 0000000000000000 R09: ffffffff8dc96917
R10: fffffbfff1b92d22 R11: 0000000000000000 R12: 0000000000000000
R13: ffff88808b9d1c80 R14: ffff88808b9d1c80 R15: ffffc90002ff8000
FS: 00007fa8a03ee700(0000) GS:ffff8880b9c00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f09896ed000 CR3: 0000000032070000 CR4: 00000000001526f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
__schedule+0x214/0x23e0 kernel/sched/core.c:5044
schedule+0xcf/0x270 kernel/sched/core.c:5226
exit_to_user_mode_loop kernel/entry/common.c:162 [inline]
exit_to_user_mode_prepare+0x13e/0x280 kernel/entry/common.c:208
irqentry_exit_to_user_mode+0x5/0x40 kernel/entry/common.c:314
asm_sysvec_reschedule_ipi+0x12/0x20 arch/x86/include/asm/idtentry.h:637
RIP: 0033:0x4665f9
Fixes: 50f2db9e368f ("netfilter: nfnetlink: consolidate callback types")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2021-05-05 07:33:24 +00:00
|
|
|
rcu_read_unlock();
|
2021-04-22 22:17:12 +00:00
|
|
|
err = -EINVAL;
|
|
|
|
break;
|
2011-07-18 14:08:07 +00:00
|
|
|
}
|
2008-10-14 18:58:31 +00:00
|
|
|
if (err == -EAGAIN)
|
|
|
|
goto replay;
|
|
|
|
return err;
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-02 16:04:53 +00:00
|
|
|
struct nfnl_err {
|
|
|
|
struct list_head head;
|
|
|
|
struct nlmsghdr *nlh;
|
|
|
|
int err;
|
2017-06-19 17:35:46 +00:00
|
|
|
struct netlink_ext_ack extack;
|
2014-09-02 16:04:53 +00:00
|
|
|
};
|
|
|
|
|
2017-06-19 17:35:46 +00:00
|
|
|
static int nfnl_err_add(struct list_head *list, struct nlmsghdr *nlh, int err,
|
|
|
|
const struct netlink_ext_ack *extack)
|
2014-09-02 16:04:53 +00:00
|
|
|
{
|
|
|
|
struct nfnl_err *nfnl_err;
|
|
|
|
|
|
|
|
nfnl_err = kmalloc(sizeof(struct nfnl_err), GFP_KERNEL);
|
|
|
|
if (nfnl_err == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
nfnl_err->nlh = nlh;
|
|
|
|
nfnl_err->err = err;
|
2017-06-19 17:35:46 +00:00
|
|
|
nfnl_err->extack = *extack;
|
2014-09-02 16:04:53 +00:00
|
|
|
list_add_tail(&nfnl_err->head, list);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void nfnl_err_del(struct nfnl_err *nfnl_err)
|
|
|
|
{
|
|
|
|
list_del(&nfnl_err->head);
|
|
|
|
kfree(nfnl_err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void nfnl_err_reset(struct list_head *err_list)
|
|
|
|
{
|
|
|
|
struct nfnl_err *nfnl_err, *next;
|
|
|
|
|
|
|
|
list_for_each_entry_safe(nfnl_err, next, err_list, head)
|
|
|
|
nfnl_err_del(nfnl_err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void nfnl_err_deliver(struct list_head *err_list, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct nfnl_err *nfnl_err, *next;
|
|
|
|
|
|
|
|
list_for_each_entry_safe(nfnl_err, next, err_list, head) {
|
2017-06-19 17:35:46 +00:00
|
|
|
netlink_ack(skb, nfnl_err->nlh, nfnl_err->err,
|
|
|
|
&nfnl_err->extack);
|
2014-09-02 16:04:53 +00:00
|
|
|
nfnl_err_del(nfnl_err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-01 14:14:25 +00:00
|
|
|
enum {
|
|
|
|
NFNL_BATCH_FAILURE = (1 << 0),
|
|
|
|
NFNL_BATCH_DONE = (1 << 1),
|
|
|
|
NFNL_BATCH_REPLAY = (1 << 2),
|
|
|
|
};
|
|
|
|
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
|
2017-02-10 11:08:17 +00:00
|
|
|
u16 subsys_id, u32 genid)
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
{
|
2014-12-10 09:21:59 +00:00
|
|
|
struct sk_buff *oskb = skb;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
struct net *net = sock_net(skb->sk);
|
|
|
|
const struct nfnetlink_subsystem *ss;
|
|
|
|
const struct nfnl_callback *nc;
|
2017-06-19 17:35:46 +00:00
|
|
|
struct netlink_ext_ack extack;
|
2017-02-18 02:35:47 +00:00
|
|
|
LIST_HEAD(err_list);
|
2015-07-01 14:14:25 +00:00
|
|
|
u32 status;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (subsys_id >= NFNL_SUBSYS_COUNT)
|
2017-04-12 12:34:04 +00:00
|
|
|
return netlink_ack(skb, nlh, -EINVAL, NULL);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
replay:
|
2015-07-01 14:14:25 +00:00
|
|
|
status = 0;
|
2020-10-29 12:50:03 +00:00
|
|
|
replay_abort:
|
2014-12-10 09:21:59 +00:00
|
|
|
skb = netlink_skb_clone(oskb, GFP_KERNEL);
|
|
|
|
if (!skb)
|
2017-04-12 12:34:04 +00:00
|
|
|
return netlink_ack(oskb, nlh, -ENOMEM, NULL);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
|
|
|
|
nfnl_lock(subsys_id);
|
2015-12-03 09:49:42 +00:00
|
|
|
ss = nfnl_dereference_protected(subsys_id);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
if (!ss) {
|
|
|
|
#ifdef CONFIG_MODULES
|
|
|
|
nfnl_unlock(subsys_id);
|
|
|
|
request_module("nfnetlink-subsys-%d", subsys_id);
|
|
|
|
nfnl_lock(subsys_id);
|
2015-12-03 09:49:42 +00:00
|
|
|
ss = nfnl_dereference_protected(subsys_id);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
if (!ss)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
nfnl_unlock(subsys_id);
|
2017-04-12 12:34:04 +00:00
|
|
|
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
|
2014-12-10 09:21:59 +00:00
|
|
|
return kfree_skb(skb);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-11 11:45:11 +00:00
|
|
|
if (!ss->valid_genid || !ss->commit || !ss->abort) {
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
nfnl_unlock(subsys_id);
|
2017-04-12 12:34:04 +00:00
|
|
|
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
|
2014-05-04 11:35:37 +00:00
|
|
|
return kfree_skb(skb);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
}
|
|
|
|
|
2018-07-11 11:45:12 +00:00
|
|
|
if (!try_module_get(ss->owner)) {
|
|
|
|
nfnl_unlock(subsys_id);
|
|
|
|
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
|
|
|
|
return kfree_skb(skb);
|
|
|
|
}
|
|
|
|
|
2018-07-11 11:45:11 +00:00
|
|
|
if (!ss->valid_genid(net, genid)) {
|
2018-07-11 11:45:12 +00:00
|
|
|
module_put(ss->owner);
|
2017-02-10 11:08:17 +00:00
|
|
|
nfnl_unlock(subsys_id);
|
2017-04-12 12:34:04 +00:00
|
|
|
netlink_ack(oskb, nlh, -ERESTART, NULL);
|
2017-02-10 11:08:17 +00:00
|
|
|
return kfree_skb(skb);
|
|
|
|
}
|
|
|
|
|
2018-07-11 11:45:14 +00:00
|
|
|
nfnl_unlock(subsys_id);
|
|
|
|
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
while (skb->len >= nlmsg_total_size(0)) {
|
|
|
|
int msglen, type;
|
|
|
|
|
2018-05-27 09:24:34 +00:00
|
|
|
if (fatal_signal_pending(current)) {
|
|
|
|
nfnl_err_reset(&err_list);
|
|
|
|
err = -EINTR;
|
|
|
|
status = NFNL_BATCH_FAILURE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2017-06-19 17:35:46 +00:00
|
|
|
memset(&extack, 0, sizeof(extack));
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
nlh = nlmsg_hdr(skb);
|
|
|
|
err = 0;
|
|
|
|
|
2016-02-02 18:36:45 +00:00
|
|
|
if (nlh->nlmsg_len < NLMSG_HDRLEN ||
|
|
|
|
skb->len < nlh->nlmsg_len ||
|
|
|
|
nlmsg_len(nlh) < sizeof(struct nfgenmsg)) {
|
|
|
|
nfnl_err_reset(&err_list);
|
|
|
|
status |= NFNL_BATCH_FAILURE;
|
|
|
|
goto done;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Only requests are handled by the kernel */
|
|
|
|
if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = nlh->nlmsg_type;
|
|
|
|
if (type == NFNL_MSG_BATCH_BEGIN) {
|
|
|
|
/* Malformed: Batch begin twice */
|
2014-09-02 16:04:53 +00:00
|
|
|
nfnl_err_reset(&err_list);
|
2015-07-01 14:14:25 +00:00
|
|
|
status |= NFNL_BATCH_FAILURE;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
goto done;
|
|
|
|
} else if (type == NFNL_MSG_BATCH_END) {
|
2015-07-01 14:14:25 +00:00
|
|
|
status |= NFNL_BATCH_DONE;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
goto done;
|
|
|
|
} else if (type < NLMSG_MIN_TYPE) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We only accept a batch with messages for the same
|
|
|
|
* subsystem.
|
|
|
|
*/
|
|
|
|
if (NFNL_SUBSYS_ID(type) != subsys_id) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
|
|
|
|
nc = nfnetlink_find_client(type, ss);
|
|
|
|
if (!nc) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
|
2021-04-22 22:17:12 +00:00
|
|
|
if (nc->type != NFNL_CB_BATCH) {
|
|
|
|
err = -EINVAL;
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
{
|
|
|
|
int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
|
2021-04-22 22:17:11 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
2018-05-30 19:17:56 +00:00
|
|
|
struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
struct nlattr *attr = (void *)nlh + min_len;
|
2021-04-22 22:17:12 +00:00
|
|
|
u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
int attrlen = nlh->nlmsg_len - min_len;
|
2021-04-22 22:17:11 +00:00
|
|
|
struct nfnl_info info = {
|
|
|
|
.net = net,
|
|
|
|
.sk = nfnlnet->nfnl,
|
|
|
|
.nlh = nlh,
|
2021-05-30 22:08:09 +00:00
|
|
|
.nfmsg = nlmsg_data(nlh),
|
2021-04-22 22:17:11 +00:00
|
|
|
.extack = &extack,
|
|
|
|
};
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
|
2018-05-30 19:17:56 +00:00
|
|
|
/* Sanity-check NFTA_MAX_ATTR */
|
|
|
|
if (ss->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto ack;
|
|
|
|
}
|
|
|
|
|
netlink: make validation more configurable for future strictness
We currently have two levels of strict validation:
1) liberal (default)
- undefined (type >= max) & NLA_UNSPEC attributes accepted
- attribute length >= expected accepted
- garbage at end of message accepted
2) strict (opt-in)
- NLA_UNSPEC attributes accepted
- attribute length >= expected accepted
Split out parsing strictness into four different options:
* TRAILING - check that there's no trailing data after parsing
attributes (in message or nested)
* MAXTYPE - reject attrs > max known type
* UNSPEC - reject attributes with NLA_UNSPEC policy entries
* STRICT_ATTRS - strictly validate attribute size
The default for future things should be *everything*.
The current *_strict() is a combination of TRAILING and MAXTYPE,
and is renamed to _deprecated_strict().
The current regular parsing has none of this, and is renamed to
*_parse_deprecated().
Additionally it allows us to selectively set one of the new flags
even on old policies. Notably, the UNSPEC flag could be useful in
this case, since it can be arranged (by filling in the policy) to
not be an incompatible userspace ABI change, but would then going
forward prevent forgetting attribute entries. Similar can apply
to the POLICY flag.
We end up with the following renames:
* nla_parse -> nla_parse_deprecated
* nla_parse_strict -> nla_parse_deprecated_strict
* nlmsg_parse -> nlmsg_parse_deprecated
* nlmsg_parse_strict -> nlmsg_parse_deprecated_strict
* nla_parse_nested -> nla_parse_nested_deprecated
* nla_validate_nested -> nla_validate_nested_deprecated
Using spatch, of course:
@@
expression TB, MAX, HEAD, LEN, POL, EXT;
@@
-nla_parse(TB, MAX, HEAD, LEN, POL, EXT)
+nla_parse_deprecated(TB, MAX, HEAD, LEN, POL, EXT)
@@
expression NLH, HDRLEN, TB, MAX, POL, EXT;
@@
-nlmsg_parse(NLH, HDRLEN, TB, MAX, POL, EXT)
+nlmsg_parse_deprecated(NLH, HDRLEN, TB, MAX, POL, EXT)
@@
expression NLH, HDRLEN, TB, MAX, POL, EXT;
@@
-nlmsg_parse_strict(NLH, HDRLEN, TB, MAX, POL, EXT)
+nlmsg_parse_deprecated_strict(NLH, HDRLEN, TB, MAX, POL, EXT)
@@
expression TB, MAX, NLA, POL, EXT;
@@
-nla_parse_nested(TB, MAX, NLA, POL, EXT)
+nla_parse_nested_deprecated(TB, MAX, NLA, POL, EXT)
@@
expression START, MAX, POL, EXT;
@@
-nla_validate_nested(START, MAX, POL, EXT)
+nla_validate_nested_deprecated(START, MAX, POL, EXT)
@@
expression NLH, HDRLEN, MAX, POL, EXT;
@@
-nlmsg_validate(NLH, HDRLEN, MAX, POL, EXT)
+nlmsg_validate_deprecated(NLH, HDRLEN, MAX, POL, EXT)
For this patch, don't actually add the strict, non-renamed versions
yet so that it breaks compile if I get it wrong.
Also, while at it, make nla_validate and nla_parse go down to a
common __nla_validate_parse() function to avoid code duplication.
Ultimately, this allows us to have very strict validation for every
new caller of nla_parse()/nlmsg_parse() etc as re-introduced in the
next patch, while existing things will continue to work as is.
In effect then, this adds fully strict validation for any new command.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-04-26 12:07:28 +00:00
|
|
|
err = nla_parse_deprecated(cda,
|
|
|
|
ss->cb[cb_id].attr_count,
|
|
|
|
attr, attrlen,
|
|
|
|
ss->cb[cb_id].policy, NULL);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
if (err < 0)
|
|
|
|
goto ack;
|
|
|
|
|
2021-04-22 22:17:12 +00:00
|
|
|
err = nc->call(skb, &info, (const struct nlattr **)cda);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
|
|
|
|
/* The lock was released to autoload some module, we
|
|
|
|
* have to abort and start from scratch using the
|
|
|
|
* original skb.
|
|
|
|
*/
|
|
|
|
if (err == -EAGAIN) {
|
2015-07-01 14:14:25 +00:00
|
|
|
status |= NFNL_BATCH_REPLAY;
|
2018-06-11 11:20:35 +00:00
|
|
|
goto done;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ack:
|
|
|
|
if (nlh->nlmsg_flags & NLM_F_ACK || err) {
|
2014-09-02 16:04:53 +00:00
|
|
|
/* Errors are delivered once the full batch has been
|
|
|
|
* processed, this avoids that the same error is
|
|
|
|
* reported several times when replaying the batch.
|
|
|
|
*/
|
2023-06-07 22:19:12 +00:00
|
|
|
if (err == -ENOMEM ||
|
|
|
|
nfnl_err_add(&err_list, nlh, err, &extack) < 0) {
|
2014-09-02 16:04:53 +00:00
|
|
|
/* We failed to enqueue an error, reset the
|
|
|
|
* list of errors and send OOM to userspace
|
|
|
|
* pointing to the batch header.
|
|
|
|
*/
|
|
|
|
nfnl_err_reset(&err_list);
|
2017-04-12 12:34:04 +00:00
|
|
|
netlink_ack(oskb, nlmsg_hdr(oskb), -ENOMEM,
|
|
|
|
NULL);
|
2015-07-01 14:14:25 +00:00
|
|
|
status |= NFNL_BATCH_FAILURE;
|
2014-09-02 16:04:53 +00:00
|
|
|
goto done;
|
|
|
|
}
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
/* We don't stop processing the batch on errors, thus,
|
|
|
|
* userspace gets all the errors that the batch
|
|
|
|
* triggers.
|
|
|
|
*/
|
|
|
|
if (err)
|
2015-07-01 14:14:25 +00:00
|
|
|
status |= NFNL_BATCH_FAILURE;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
}
|
2018-06-11 11:20:35 +00:00
|
|
|
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
|
|
|
|
if (msglen > skb->len)
|
|
|
|
msglen = skb->len;
|
|
|
|
skb_pull(skb, msglen);
|
|
|
|
}
|
|
|
|
done:
|
2015-07-01 14:14:25 +00:00
|
|
|
if (status & NFNL_BATCH_REPLAY) {
|
2020-10-29 12:50:03 +00:00
|
|
|
ss->abort(net, oskb, NFNL_ABORT_AUTOLOAD);
|
2015-07-01 14:14:25 +00:00
|
|
|
nfnl_err_reset(&err_list);
|
|
|
|
kfree_skb(skb);
|
2018-07-11 11:45:12 +00:00
|
|
|
module_put(ss->owner);
|
2015-07-01 14:14:25 +00:00
|
|
|
goto replay;
|
|
|
|
} else if (status == NFNL_BATCH_DONE) {
|
2018-05-24 22:25:47 +00:00
|
|
|
err = ss->commit(net, oskb);
|
|
|
|
if (err == -EAGAIN) {
|
|
|
|
status |= NFNL_BATCH_REPLAY;
|
|
|
|
goto done;
|
|
|
|
} else if (err) {
|
2020-10-29 12:50:03 +00:00
|
|
|
ss->abort(net, oskb, NFNL_ABORT_NONE);
|
2018-05-24 22:25:47 +00:00
|
|
|
netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL);
|
|
|
|
}
|
2015-07-01 14:14:25 +00:00
|
|
|
} else {
|
2020-10-29 12:50:03 +00:00
|
|
|
enum nfnl_abort_action abort_action;
|
|
|
|
|
|
|
|
if (status & NFNL_BATCH_FAILURE)
|
|
|
|
abort_action = NFNL_ABORT_NONE;
|
|
|
|
else
|
|
|
|
abort_action = NFNL_ABORT_VALIDATE;
|
|
|
|
|
|
|
|
err = ss->abort(net, oskb, abort_action);
|
|
|
|
if (err == -EAGAIN) {
|
|
|
|
nfnl_err_reset(&err_list);
|
|
|
|
kfree_skb(skb);
|
|
|
|
module_put(ss->owner);
|
|
|
|
status |= NFNL_BATCH_FAILURE;
|
|
|
|
goto replay_abort;
|
|
|
|
}
|
2015-07-01 14:14:25 +00:00
|
|
|
}
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
|
2014-09-02 16:04:53 +00:00
|
|
|
nfnl_err_deliver(&err_list, oskb);
|
2014-12-10 09:21:59 +00:00
|
|
|
kfree_skb(skb);
|
2018-07-11 11:45:12 +00:00
|
|
|
module_put(ss->owner);
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
}
|
|
|
|
|
2017-02-10 11:08:17 +00:00
|
|
|
static const struct nla_policy nfnl_batch_policy[NFNL_BATCH_MAX + 1] = {
|
|
|
|
[NFNL_BATCH_GENID] = { .type = NLA_U32 },
|
|
|
|
};
|
|
|
|
|
2017-02-10 11:08:14 +00:00
|
|
|
static void nfnetlink_rcv_skb_batch(struct sk_buff *skb, struct nlmsghdr *nlh)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2017-02-10 11:08:17 +00:00
|
|
|
int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
|
|
|
|
struct nlattr *attr = (void *)nlh + min_len;
|
|
|
|
struct nlattr *cda[NFNL_BATCH_MAX + 1];
|
|
|
|
int attrlen = nlh->nlmsg_len - min_len;
|
2017-02-10 11:08:14 +00:00
|
|
|
struct nfgenmsg *nfgenmsg;
|
2017-02-10 11:08:17 +00:00
|
|
|
int msglen, err;
|
|
|
|
u32 gen_id = 0;
|
2017-02-10 11:08:08 +00:00
|
|
|
u16 res_id;
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
|
2017-02-10 11:08:14 +00:00
|
|
|
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
|
|
|
|
if (msglen > skb->len)
|
|
|
|
msglen = skb->len;
|
|
|
|
|
2017-06-07 13:50:38 +00:00
|
|
|
if (skb->len < NLMSG_HDRLEN + sizeof(struct nfgenmsg))
|
2017-02-10 11:08:14 +00:00
|
|
|
return;
|
|
|
|
|
netlink: make validation more configurable for future strictness
We currently have two levels of strict validation:
1) liberal (default)
- undefined (type >= max) & NLA_UNSPEC attributes accepted
- attribute length >= expected accepted
- garbage at end of message accepted
2) strict (opt-in)
- NLA_UNSPEC attributes accepted
- attribute length >= expected accepted
Split out parsing strictness into four different options:
* TRAILING - check that there's no trailing data after parsing
attributes (in message or nested)
* MAXTYPE - reject attrs > max known type
* UNSPEC - reject attributes with NLA_UNSPEC policy entries
* STRICT_ATTRS - strictly validate attribute size
The default for future things should be *everything*.
The current *_strict() is a combination of TRAILING and MAXTYPE,
and is renamed to _deprecated_strict().
The current regular parsing has none of this, and is renamed to
*_parse_deprecated().
Additionally it allows us to selectively set one of the new flags
even on old policies. Notably, the UNSPEC flag could be useful in
this case, since it can be arranged (by filling in the policy) to
not be an incompatible userspace ABI change, but would then going
forward prevent forgetting attribute entries. Similar can apply
to the POLICY flag.
We end up with the following renames:
* nla_parse -> nla_parse_deprecated
* nla_parse_strict -> nla_parse_deprecated_strict
* nlmsg_parse -> nlmsg_parse_deprecated
* nlmsg_parse_strict -> nlmsg_parse_deprecated_strict
* nla_parse_nested -> nla_parse_nested_deprecated
* nla_validate_nested -> nla_validate_nested_deprecated
Using spatch, of course:
@@
expression TB, MAX, HEAD, LEN, POL, EXT;
@@
-nla_parse(TB, MAX, HEAD, LEN, POL, EXT)
+nla_parse_deprecated(TB, MAX, HEAD, LEN, POL, EXT)
@@
expression NLH, HDRLEN, TB, MAX, POL, EXT;
@@
-nlmsg_parse(NLH, HDRLEN, TB, MAX, POL, EXT)
+nlmsg_parse_deprecated(NLH, HDRLEN, TB, MAX, POL, EXT)
@@
expression NLH, HDRLEN, TB, MAX, POL, EXT;
@@
-nlmsg_parse_strict(NLH, HDRLEN, TB, MAX, POL, EXT)
+nlmsg_parse_deprecated_strict(NLH, HDRLEN, TB, MAX, POL, EXT)
@@
expression TB, MAX, NLA, POL, EXT;
@@
-nla_parse_nested(TB, MAX, NLA, POL, EXT)
+nla_parse_nested_deprecated(TB, MAX, NLA, POL, EXT)
@@
expression START, MAX, POL, EXT;
@@
-nla_validate_nested(START, MAX, POL, EXT)
+nla_validate_nested_deprecated(START, MAX, POL, EXT)
@@
expression NLH, HDRLEN, MAX, POL, EXT;
@@
-nlmsg_validate(NLH, HDRLEN, MAX, POL, EXT)
+nlmsg_validate_deprecated(NLH, HDRLEN, MAX, POL, EXT)
For this patch, don't actually add the strict, non-renamed versions
yet so that it breaks compile if I get it wrong.
Also, while at it, make nla_validate and nla_parse go down to a
common __nla_validate_parse() function to avoid code duplication.
Ultimately, this allows us to have very strict validation for every
new caller of nla_parse()/nlmsg_parse() etc as re-introduced in the
next patch, while existing things will continue to work as is.
In effect then, this adds fully strict validation for any new command.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-04-26 12:07:28 +00:00
|
|
|
err = nla_parse_deprecated(cda, NFNL_BATCH_MAX, attr, attrlen,
|
|
|
|
nfnl_batch_policy, NULL);
|
2017-02-10 11:08:17 +00:00
|
|
|
if (err < 0) {
|
2017-04-12 12:34:04 +00:00
|
|
|
netlink_ack(skb, nlh, err, NULL);
|
2017-02-10 11:08:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cda[NFNL_BATCH_GENID])
|
|
|
|
gen_id = ntohl(nla_get_be32(cda[NFNL_BATCH_GENID]));
|
|
|
|
|
2017-02-10 11:08:14 +00:00
|
|
|
nfgenmsg = nlmsg_data(nlh);
|
|
|
|
skb_pull(skb, msglen);
|
|
|
|
/* Work around old nft using host byte order */
|
2022-06-23 13:05:09 +00:00
|
|
|
if (nfgenmsg->res_id == (__force __be16)NFNL_SUBSYS_NFTABLES)
|
2017-02-10 11:08:14 +00:00
|
|
|
res_id = NFNL_SUBSYS_NFTABLES;
|
|
|
|
else
|
|
|
|
res_id = ntohs(nfgenmsg->res_id);
|
|
|
|
|
2017-02-10 11:08:17 +00:00
|
|
|
nfnetlink_rcv_batch(skb, nlh, res_id, gen_id);
|
2017-02-10 11:08:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void nfnetlink_rcv(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct nlmsghdr *nlh = nlmsg_hdr(skb);
|
|
|
|
|
2017-06-07 13:50:38 +00:00
|
|
|
if (skb->len < NLMSG_HDRLEN ||
|
|
|
|
nlh->nlmsg_len < NLMSG_HDRLEN ||
|
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds
two new control messages:
* NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch,
the nfgenmsg->res_id indicates the nfnetlink subsystem ID.
* NFNL_MSG_BATCH_END, that results in the invocation of the
ss->commit callback function. If not specified or an error
ocurred in the batch, the ss->abort function is invoked
instead.
The end message represents the commit operation in nftables, the
lack of end message results in an abort. This patch also adds the
.call_batch function that is only called from the batch receival
path.
This patch adds atomic rule updates and dumps based on
bitmask generations. This allows to atomically commit a set of
rule-set updates incrementally without altering the internal
state of existing nf_tables expressions/matches/targets.
The idea consists of using a generation cursor of 1 bit and
a bitmask of 2 bits per rule. Assuming the gencursor is 0,
then the genmask (expressed as a bitmask) can be interpreted
as:
00 active in the present, will be active in the next generation.
01 inactive in the present, will be active in the next generation.
10 active in the present, will be deleted in the next generation.
^
gencursor
Once you invoke the transition to the next generation, the global
gencursor is updated:
00 active in the present, will be active in the next generation.
01 active in the present, needs to zero its future, it becomes 00.
10 inactive in the present, delete now.
^
gencursor
If a dump is in progress and nf_tables enters a new generation,
the dump will stop and return -EBUSY to let userspace know that
it has to retry again. In order to invalidate dumps, a global
genctr counter is increased everytime nf_tables enters a new
generation.
This new operation can be used from the user-space utility
that controls the firewall, eg.
nft -f restore
The rule updates contained in `file' will be applied atomically.
cat file
-----
add filter INPUT ip saddr 1.1.1.1 counter accept #1
del filter INPUT ip daddr 2.2.2.2 counter drop #2
-EOF-
Note that the rule 1 will be inactive until the transition to the
next generation, the rule 2 will be evicted in the next generation.
There is a penalty during the rule update due to the branch
misprediction in the packet matching framework. But that should be
quickly resolved once the iteration over the commit list that
contain rules that require updates is finished.
Event notification happens once the rule-set update has been
committed. So we skip notifications is case the rule-set update
is aborted, which can happen in case that the rule-set is tested
to apply correctly.
This patch squashed the following patches from Pablo:
* nf_tables: atomic rule updates and dumps
* nf_tables: get rid of per rule list_head for commits
* nf_tables: use per netns commit list
* nfnetlink: add batch support and use it from nf_tables
* nf_tables: all rule updates are transactional
* nf_tables: attach replacement rule after stale one
* nf_tables: do not allow deletion/replacement of stale rules
* nf_tables: remove unused NFTA_RULE_FLAGS
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2013-10-14 09:05:33 +00:00
|
|
|
skb->len < nlh->nlmsg_len)
|
|
|
|
return;
|
|
|
|
|
2014-04-23 21:29:27 +00:00
|
|
|
if (!netlink_net_capable(skb, CAP_NET_ADMIN)) {
|
2017-04-12 12:34:04 +00:00
|
|
|
netlink_ack(skb, nlh, -EPERM, NULL);
|
2013-11-07 18:59:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-02-10 11:08:14 +00:00
|
|
|
if (nlh->nlmsg_type == NFNL_MSG_BATCH_BEGIN)
|
|
|
|
nfnetlink_rcv_skb_batch(skb, nlh);
|
|
|
|
else
|
2017-04-02 09:22:12 +00:00
|
|
|
netlink_rcv_skb(skb, nfnetlink_rcv_msg);
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
|
|
|
|
2022-08-05 08:59:57 +00:00
|
|
|
static void nfnetlink_bind_event(struct net *net, unsigned int group)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
|
|
|
int type, group_bit;
|
|
|
|
u8 v;
|
|
|
|
|
|
|
|
/* All NFNLGRP_CONNTRACK_* group bits fit into u8.
|
|
|
|
* The other groups are not relevant and can be ignored.
|
|
|
|
*/
|
|
|
|
if (group >= 8)
|
|
|
|
return;
|
|
|
|
|
|
|
|
type = nfnl_group2type[group];
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case NFNL_SUBSYS_CTNETLINK:
|
|
|
|
break;
|
|
|
|
case NFNL_SUBSYS_CTNETLINK_EXP:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
group_bit = (1 << group);
|
|
|
|
|
|
|
|
spin_lock(&nfnl_grp_active_lock);
|
2023-02-20 16:24:00 +00:00
|
|
|
v = READ_ONCE(nf_ctnetlink_has_listener);
|
2022-08-05 08:59:57 +00:00
|
|
|
if ((v & group_bit) == 0) {
|
|
|
|
v |= group_bit;
|
|
|
|
|
|
|
|
/* read concurrently without nfnl_grp_active_lock held. */
|
2023-02-20 16:24:00 +00:00
|
|
|
WRITE_ONCE(nf_ctnetlink_has_listener, v);
|
2022-08-05 08:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock(&nfnl_grp_active_lock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-12-23 20:00:06 +00:00
|
|
|
static int nfnetlink_bind(struct net *net, int group)
|
2012-06-29 06:15:22 +00:00
|
|
|
{
|
|
|
|
const struct nfnetlink_subsystem *ss;
|
2014-11-14 17:14:33 +00:00
|
|
|
int type;
|
|
|
|
|
|
|
|
if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
|
2015-01-04 14:20:41 +00:00
|
|
|
return 0;
|
2014-11-14 17:14:33 +00:00
|
|
|
|
|
|
|
type = nfnl_group2type[group];
|
2012-06-29 06:15:22 +00:00
|
|
|
|
|
|
|
rcu_read_lock();
|
2015-10-27 12:20:25 +00:00
|
|
|
ss = nfnetlink_get_subsys(type << 8);
|
2012-06-29 06:15:22 +00:00
|
|
|
rcu_read_unlock();
|
2014-04-23 01:31:53 +00:00
|
|
|
if (!ss)
|
2019-07-02 19:41:40 +00:00
|
|
|
request_module_nowait("nfnetlink-subsys-%d", type);
|
2022-04-25 13:15:41 +00:00
|
|
|
|
2022-08-05 08:59:57 +00:00
|
|
|
nfnetlink_bind_event(net, group);
|
2014-04-23 01:31:54 +00:00
|
|
|
return 0;
|
2012-06-29 06:15:22 +00:00
|
|
|
}
|
2022-04-25 13:15:41 +00:00
|
|
|
|
|
|
|
static void nfnetlink_unbind(struct net *net, int group)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
2022-08-05 08:59:57 +00:00
|
|
|
int type, group_bit;
|
|
|
|
|
2022-05-19 22:02:03 +00:00
|
|
|
if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
|
|
|
|
return;
|
2022-04-25 13:15:41 +00:00
|
|
|
|
2022-08-05 08:59:57 +00:00
|
|
|
type = nfnl_group2type[group];
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case NFNL_SUBSYS_CTNETLINK:
|
|
|
|
break;
|
|
|
|
case NFNL_SUBSYS_CTNETLINK_EXP:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ctnetlink_has_listener is u8 */
|
|
|
|
if (group >= 8)
|
|
|
|
return;
|
|
|
|
|
|
|
|
group_bit = (1 << group);
|
|
|
|
|
|
|
|
spin_lock(&nfnl_grp_active_lock);
|
|
|
|
if (!nfnetlink_has_listeners(net, group)) {
|
2023-02-20 16:24:00 +00:00
|
|
|
u8 v = READ_ONCE(nf_ctnetlink_has_listener);
|
2022-08-05 08:59:57 +00:00
|
|
|
|
|
|
|
v &= ~group_bit;
|
|
|
|
|
|
|
|
/* read concurrently without nfnl_grp_active_lock held. */
|
2023-02-20 16:24:00 +00:00
|
|
|
WRITE_ONCE(nf_ctnetlink_has_listener, v);
|
2022-04-25 13:15:41 +00:00
|
|
|
}
|
2022-08-05 08:59:57 +00:00
|
|
|
spin_unlock(&nfnl_grp_active_lock);
|
2012-06-29 06:15:22 +00:00
|
|
|
#endif
|
2022-04-25 13:15:41 +00:00
|
|
|
}
|
2012-06-29 06:15:22 +00:00
|
|
|
|
2010-01-13 15:02:14 +00:00
|
|
|
static int __net_init nfnetlink_net_init(struct net *net)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
2012-06-29 06:15:21 +00:00
|
|
|
struct netlink_kernel_cfg cfg = {
|
|
|
|
.groups = NFNLGRP_MAX,
|
|
|
|
.input = nfnetlink_rcv,
|
2012-06-29 06:15:22 +00:00
|
|
|
.bind = nfnetlink_bind,
|
2022-04-25 13:15:41 +00:00
|
|
|
.unbind = nfnetlink_unbind,
|
2012-06-29 06:15:21 +00:00
|
|
|
};
|
2010-01-13 15:02:14 +00:00
|
|
|
|
2021-04-01 14:11:05 +00:00
|
|
|
nfnlnet->nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, &cfg);
|
|
|
|
if (!nfnlnet->nfnl)
|
2010-01-13 15:02:14 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
return 0;
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
|
|
|
|
2010-01-13 15:02:14 +00:00
|
|
|
static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list)
|
2005-08-10 02:30:24 +00:00
|
|
|
{
|
2021-04-01 14:11:05 +00:00
|
|
|
struct nfnl_net *nfnlnet;
|
2010-01-13 15:02:14 +00:00
|
|
|
struct net *net;
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2021-04-01 14:11:05 +00:00
|
|
|
list_for_each_entry(net, net_exit_list, exit_list) {
|
|
|
|
nfnlnet = nfnl_pernet(net);
|
|
|
|
|
|
|
|
netlink_kernel_release(nfnlnet->nfnl);
|
|
|
|
}
|
2010-01-13 15:02:14 +00:00
|
|
|
}
|
2005-08-10 02:30:24 +00:00
|
|
|
|
2010-01-13 15:02:14 +00:00
|
|
|
static struct pernet_operations nfnetlink_net_ops = {
|
|
|
|
.init = nfnetlink_net_init,
|
|
|
|
.exit_batch = nfnetlink_net_exit_batch,
|
2021-04-01 14:11:05 +00:00
|
|
|
.id = &nfnetlink_pernet_id,
|
|
|
|
.size = sizeof(struct nfnl_net),
|
2010-01-13 15:02:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int __init nfnetlink_init(void)
|
|
|
|
{
|
2013-02-05 00:50:26 +00:00
|
|
|
int i;
|
|
|
|
|
2014-11-14 17:14:33 +00:00
|
|
|
for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
|
|
|
|
BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
|
|
|
|
|
2013-02-05 00:50:26 +00:00
|
|
|
for (i=0; i<NFNL_SUBSYS_COUNT; i++)
|
2020-10-02 11:51:29 +00:00
|
|
|
__mutex_init(&table[i].mutex, nfnl_lockdep_names[i], &nfnl_lockdep_keys[i]);
|
2013-02-05 00:50:26 +00:00
|
|
|
|
2010-01-13 15:02:14 +00:00
|
|
|
return register_pernet_subsys(&nfnetlink_net_ops);
|
2005-08-10 02:30:24 +00:00
|
|
|
}
|
|
|
|
|
2010-01-13 15:02:14 +00:00
|
|
|
static void __exit nfnetlink_exit(void)
|
|
|
|
{
|
|
|
|
unregister_pernet_subsys(&nfnetlink_net_ops);
|
|
|
|
}
|
2005-08-10 02:30:24 +00:00
|
|
|
module_init(nfnetlink_init);
|
|
|
|
module_exit(nfnetlink_exit);
|