cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nfnetlink.c (18624B)


      1/* Netfilter messages via netlink socket. Allows for user space
      2 * protocol helpers and general trouble making from userspace.
      3 *
      4 * (C) 2001 by Jay Schulist <jschlst@samba.org>,
      5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
      6 * (C) 2005-2017 by Pablo Neira Ayuso <pablo@netfilter.org>
      7 *
      8 * Initial netfilter messages via netlink development funded and
      9 * generally made possible by Network Robots, Inc. (www.networkrobots.com)
     10 *
     11 * Further development of this code funded by Astaro AG (http://www.astaro.com)
     12 *
     13 * This software may be used and distributed according to the terms
     14 * of the GNU General Public License, incorporated herein by reference.
     15 */
     16
     17#include <linux/module.h>
     18#include <linux/types.h>
     19#include <linux/socket.h>
     20#include <linux/kernel.h>
     21#include <linux/string.h>
     22#include <linux/sockios.h>
     23#include <linux/net.h>
     24#include <linux/skbuff.h>
     25#include <linux/uaccess.h>
     26#include <net/sock.h>
     27#include <linux/init.h>
     28#include <linux/sched/signal.h>
     29
     30#include <net/netlink.h>
     31#include <net/netns/generic.h>
     32#include <linux/netfilter/nfnetlink.h>
     33
     34MODULE_LICENSE("GPL");
     35MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
     36MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
     37MODULE_DESCRIPTION("Netfilter messages via netlink socket");
     38
     39#define nfnl_dereference_protected(id) \
     40	rcu_dereference_protected(table[(id)].subsys, \
     41				  lockdep_nfnl_is_held((id)))
     42
     43#define NFNL_MAX_ATTR_COUNT	32
     44
     45static unsigned int nfnetlink_pernet_id __read_mostly;
     46
     47struct nfnl_net {
     48	struct sock *nfnl;
     49};
     50
     51static struct {
     52	struct mutex				mutex;
     53	const struct nfnetlink_subsystem __rcu	*subsys;
     54} table[NFNL_SUBSYS_COUNT];
     55
     56static struct lock_class_key nfnl_lockdep_keys[NFNL_SUBSYS_COUNT];
     57
     58static const char *const nfnl_lockdep_names[NFNL_SUBSYS_COUNT] = {
     59	[NFNL_SUBSYS_NONE] = "nfnl_subsys_none",
     60	[NFNL_SUBSYS_CTNETLINK] = "nfnl_subsys_ctnetlink",
     61	[NFNL_SUBSYS_CTNETLINK_EXP] = "nfnl_subsys_ctnetlink_exp",
     62	[NFNL_SUBSYS_QUEUE] = "nfnl_subsys_queue",
     63	[NFNL_SUBSYS_ULOG] = "nfnl_subsys_ulog",
     64	[NFNL_SUBSYS_OSF] = "nfnl_subsys_osf",
     65	[NFNL_SUBSYS_IPSET] = "nfnl_subsys_ipset",
     66	[NFNL_SUBSYS_ACCT] = "nfnl_subsys_acct",
     67	[NFNL_SUBSYS_CTNETLINK_TIMEOUT] = "nfnl_subsys_cttimeout",
     68	[NFNL_SUBSYS_CTHELPER] = "nfnl_subsys_cthelper",
     69	[NFNL_SUBSYS_NFTABLES] = "nfnl_subsys_nftables",
     70	[NFNL_SUBSYS_NFT_COMPAT] = "nfnl_subsys_nftcompat",
     71	[NFNL_SUBSYS_HOOK] = "nfnl_subsys_hook",
     72};
     73
     74static const int nfnl_group2type[NFNLGRP_MAX+1] = {
     75	[NFNLGRP_CONNTRACK_NEW]		= NFNL_SUBSYS_CTNETLINK,
     76	[NFNLGRP_CONNTRACK_UPDATE]	= NFNL_SUBSYS_CTNETLINK,
     77	[NFNLGRP_CONNTRACK_DESTROY]	= NFNL_SUBSYS_CTNETLINK,
     78	[NFNLGRP_CONNTRACK_EXP_NEW]	= NFNL_SUBSYS_CTNETLINK_EXP,
     79	[NFNLGRP_CONNTRACK_EXP_UPDATE]	= NFNL_SUBSYS_CTNETLINK_EXP,
     80	[NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
     81	[NFNLGRP_NFTABLES]		= NFNL_SUBSYS_NFTABLES,
     82	[NFNLGRP_ACCT_QUOTA]		= NFNL_SUBSYS_ACCT,
     83	[NFNLGRP_NFTRACE]		= NFNL_SUBSYS_NFTABLES,
     84};
     85
     86static struct nfnl_net *nfnl_pernet(struct net *net)
     87{
     88	return net_generic(net, nfnetlink_pernet_id);
     89}
     90
     91void nfnl_lock(__u8 subsys_id)
     92{
     93	mutex_lock(&table[subsys_id].mutex);
     94}
     95EXPORT_SYMBOL_GPL(nfnl_lock);
     96
     97void nfnl_unlock(__u8 subsys_id)
     98{
     99	mutex_unlock(&table[subsys_id].mutex);
    100}
    101EXPORT_SYMBOL_GPL(nfnl_unlock);
    102
    103#ifdef CONFIG_PROVE_LOCKING
    104bool lockdep_nfnl_is_held(u8 subsys_id)
    105{
    106	return lockdep_is_held(&table[subsys_id].mutex);
    107}
    108EXPORT_SYMBOL_GPL(lockdep_nfnl_is_held);
    109#endif
    110
    111int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
    112{
    113	u8 cb_id;
    114
    115	/* Sanity-check attr_count size to avoid stack buffer overflow. */
    116	for (cb_id = 0; cb_id < n->cb_count; cb_id++)
    117		if (WARN_ON(n->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT))
    118			return -EINVAL;
    119
    120	nfnl_lock(n->subsys_id);
    121	if (table[n->subsys_id].subsys) {
    122		nfnl_unlock(n->subsys_id);
    123		return -EBUSY;
    124	}
    125	rcu_assign_pointer(table[n->subsys_id].subsys, n);
    126	nfnl_unlock(n->subsys_id);
    127
    128	return 0;
    129}
    130EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
    131
    132int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
    133{
    134	nfnl_lock(n->subsys_id);
    135	table[n->subsys_id].subsys = NULL;
    136	nfnl_unlock(n->subsys_id);
    137	synchronize_rcu();
    138	return 0;
    139}
    140EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
    141
    142static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u16 type)
    143{
    144	u8 subsys_id = NFNL_SUBSYS_ID(type);
    145
    146	if (subsys_id >= NFNL_SUBSYS_COUNT)
    147		return NULL;
    148
    149	return rcu_dereference(table[subsys_id].subsys);
    150}
    151
    152static inline const struct nfnl_callback *
    153nfnetlink_find_client(u16 type, const struct nfnetlink_subsystem *ss)
    154{
    155	u8 cb_id = NFNL_MSG_TYPE(type);
    156
    157	if (cb_id >= ss->cb_count)
    158		return NULL;
    159
    160	return &ss->cb[cb_id];
    161}
    162
    163int nfnetlink_has_listeners(struct net *net, unsigned int group)
    164{
    165	struct nfnl_net *nfnlnet = nfnl_pernet(net);
    166
    167	return netlink_has_listeners(nfnlnet->nfnl, group);
    168}
    169EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
    170
    171int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid,
    172		   unsigned int group, int echo, gfp_t flags)
    173{
    174	struct nfnl_net *nfnlnet = nfnl_pernet(net);
    175
    176	return nlmsg_notify(nfnlnet->nfnl, skb, portid, group, echo, flags);
    177}
    178EXPORT_SYMBOL_GPL(nfnetlink_send);
    179
    180int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error)
    181{
    182	struct nfnl_net *nfnlnet = nfnl_pernet(net);
    183
    184	return netlink_set_err(nfnlnet->nfnl, portid, group, error);
    185}
    186EXPORT_SYMBOL_GPL(nfnetlink_set_err);
    187
    188int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid)
    189{
    190	struct nfnl_net *nfnlnet = nfnl_pernet(net);
    191	int err;
    192
    193	err = nlmsg_unicast(nfnlnet->nfnl, skb, portid);
    194	if (err == -EAGAIN)
    195		err = -ENOBUFS;
    196
    197	return err;
    198}
    199EXPORT_SYMBOL_GPL(nfnetlink_unicast);
    200
    201void nfnetlink_broadcast(struct net *net, struct sk_buff *skb, __u32 portid,
    202			 __u32 group, gfp_t allocation)
    203{
    204	struct nfnl_net *nfnlnet = nfnl_pernet(net);
    205
    206	netlink_broadcast(nfnlnet->nfnl, skb, portid, group, allocation);
    207}
    208EXPORT_SYMBOL_GPL(nfnetlink_broadcast);
    209
    210/* Process one complete nfnetlink message. */
    211static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
    212			     struct netlink_ext_ack *extack)
    213{
    214	struct net *net = sock_net(skb->sk);
    215	const struct nfnl_callback *nc;
    216	const struct nfnetlink_subsystem *ss;
    217	int type, err;
    218
    219	/* All the messages must at least contain nfgenmsg */
    220	if (nlmsg_len(nlh) < sizeof(struct nfgenmsg))
    221		return 0;
    222
    223	type = nlh->nlmsg_type;
    224replay:
    225	rcu_read_lock();
    226
    227	ss = nfnetlink_get_subsys(type);
    228	if (!ss) {
    229#ifdef CONFIG_MODULES
    230		rcu_read_unlock();
    231		request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
    232		rcu_read_lock();
    233		ss = nfnetlink_get_subsys(type);
    234		if (!ss)
    235#endif
    236		{
    237			rcu_read_unlock();
    238			return -EINVAL;
    239		}
    240	}
    241
    242	nc = nfnetlink_find_client(type, ss);
    243	if (!nc) {
    244		rcu_read_unlock();
    245		return -EINVAL;
    246	}
    247
    248	{
    249		int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
    250		struct nfnl_net *nfnlnet = nfnl_pernet(net);
    251		u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
    252		struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
    253		struct nlattr *attr = (void *)nlh + min_len;
    254		int attrlen = nlh->nlmsg_len - min_len;
    255		__u8 subsys_id = NFNL_SUBSYS_ID(type);
    256		struct nfnl_info info = {
    257			.net	= net,
    258			.sk	= nfnlnet->nfnl,
    259			.nlh	= nlh,
    260			.nfmsg	= nlmsg_data(nlh),
    261			.extack	= extack,
    262		};
    263
    264		/* Sanity-check NFNL_MAX_ATTR_COUNT */
    265		if (ss->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT) {
    266			rcu_read_unlock();
    267			return -ENOMEM;
    268		}
    269
    270		err = nla_parse_deprecated(cda, ss->cb[cb_id].attr_count,
    271					   attr, attrlen,
    272					   ss->cb[cb_id].policy, extack);
    273		if (err < 0) {
    274			rcu_read_unlock();
    275			return err;
    276		}
    277
    278		if (!nc->call) {
    279			rcu_read_unlock();
    280			return -EINVAL;
    281		}
    282
    283		switch (nc->type) {
    284		case NFNL_CB_RCU:
    285			err = nc->call(skb, &info, (const struct nlattr **)cda);
    286			rcu_read_unlock();
    287			break;
    288		case NFNL_CB_MUTEX:
    289			rcu_read_unlock();
    290			nfnl_lock(subsys_id);
    291			if (nfnl_dereference_protected(subsys_id) != ss ||
    292			    nfnetlink_find_client(type, ss) != nc) {
    293				err = -EAGAIN;
    294				break;
    295			}
    296			err = nc->call(skb, &info, (const struct nlattr **)cda);
    297			nfnl_unlock(subsys_id);
    298			break;
    299		default:
    300			rcu_read_unlock();
    301			err = -EINVAL;
    302			break;
    303		}
    304		if (err == -EAGAIN)
    305			goto replay;
    306		return err;
    307	}
    308}
    309
    310struct nfnl_err {
    311	struct list_head	head;
    312	struct nlmsghdr		*nlh;
    313	int			err;
    314	struct netlink_ext_ack	extack;
    315};
    316
    317static int nfnl_err_add(struct list_head *list, struct nlmsghdr *nlh, int err,
    318			const struct netlink_ext_ack *extack)
    319{
    320	struct nfnl_err *nfnl_err;
    321
    322	nfnl_err = kmalloc(sizeof(struct nfnl_err), GFP_KERNEL);
    323	if (nfnl_err == NULL)
    324		return -ENOMEM;
    325
    326	nfnl_err->nlh = nlh;
    327	nfnl_err->err = err;
    328	nfnl_err->extack = *extack;
    329	list_add_tail(&nfnl_err->head, list);
    330
    331	return 0;
    332}
    333
    334static void nfnl_err_del(struct nfnl_err *nfnl_err)
    335{
    336	list_del(&nfnl_err->head);
    337	kfree(nfnl_err);
    338}
    339
    340static void nfnl_err_reset(struct list_head *err_list)
    341{
    342	struct nfnl_err *nfnl_err, *next;
    343
    344	list_for_each_entry_safe(nfnl_err, next, err_list, head)
    345		nfnl_err_del(nfnl_err);
    346}
    347
    348static void nfnl_err_deliver(struct list_head *err_list, struct sk_buff *skb)
    349{
    350	struct nfnl_err *nfnl_err, *next;
    351
    352	list_for_each_entry_safe(nfnl_err, next, err_list, head) {
    353		netlink_ack(skb, nfnl_err->nlh, nfnl_err->err,
    354			    &nfnl_err->extack);
    355		nfnl_err_del(nfnl_err);
    356	}
    357}
    358
    359enum {
    360	NFNL_BATCH_FAILURE	= (1 << 0),
    361	NFNL_BATCH_DONE		= (1 << 1),
    362	NFNL_BATCH_REPLAY	= (1 << 2),
    363};
    364
    365static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
    366				u16 subsys_id, u32 genid)
    367{
    368	struct sk_buff *oskb = skb;
    369	struct net *net = sock_net(skb->sk);
    370	const struct nfnetlink_subsystem *ss;
    371	const struct nfnl_callback *nc;
    372	struct netlink_ext_ack extack;
    373	LIST_HEAD(err_list);
    374	u32 status;
    375	int err;
    376
    377	if (subsys_id >= NFNL_SUBSYS_COUNT)
    378		return netlink_ack(skb, nlh, -EINVAL, NULL);
    379replay:
    380	status = 0;
    381replay_abort:
    382	skb = netlink_skb_clone(oskb, GFP_KERNEL);
    383	if (!skb)
    384		return netlink_ack(oskb, nlh, -ENOMEM, NULL);
    385
    386	nfnl_lock(subsys_id);
    387	ss = nfnl_dereference_protected(subsys_id);
    388	if (!ss) {
    389#ifdef CONFIG_MODULES
    390		nfnl_unlock(subsys_id);
    391		request_module("nfnetlink-subsys-%d", subsys_id);
    392		nfnl_lock(subsys_id);
    393		ss = nfnl_dereference_protected(subsys_id);
    394		if (!ss)
    395#endif
    396		{
    397			nfnl_unlock(subsys_id);
    398			netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
    399			return kfree_skb(skb);
    400		}
    401	}
    402
    403	if (!ss->valid_genid || !ss->commit || !ss->abort) {
    404		nfnl_unlock(subsys_id);
    405		netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
    406		return kfree_skb(skb);
    407	}
    408
    409	if (!try_module_get(ss->owner)) {
    410		nfnl_unlock(subsys_id);
    411		netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
    412		return kfree_skb(skb);
    413	}
    414
    415	if (!ss->valid_genid(net, genid)) {
    416		module_put(ss->owner);
    417		nfnl_unlock(subsys_id);
    418		netlink_ack(oskb, nlh, -ERESTART, NULL);
    419		return kfree_skb(skb);
    420	}
    421
    422	nfnl_unlock(subsys_id);
    423
    424	while (skb->len >= nlmsg_total_size(0)) {
    425		int msglen, type;
    426
    427		if (fatal_signal_pending(current)) {
    428			nfnl_err_reset(&err_list);
    429			err = -EINTR;
    430			status = NFNL_BATCH_FAILURE;
    431			goto done;
    432		}
    433
    434		memset(&extack, 0, sizeof(extack));
    435		nlh = nlmsg_hdr(skb);
    436		err = 0;
    437
    438		if (nlh->nlmsg_len < NLMSG_HDRLEN ||
    439		    skb->len < nlh->nlmsg_len ||
    440		    nlmsg_len(nlh) < sizeof(struct nfgenmsg)) {
    441			nfnl_err_reset(&err_list);
    442			status |= NFNL_BATCH_FAILURE;
    443			goto done;
    444		}
    445
    446		/* Only requests are handled by the kernel */
    447		if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
    448			err = -EINVAL;
    449			goto ack;
    450		}
    451
    452		type = nlh->nlmsg_type;
    453		if (type == NFNL_MSG_BATCH_BEGIN) {
    454			/* Malformed: Batch begin twice */
    455			nfnl_err_reset(&err_list);
    456			status |= NFNL_BATCH_FAILURE;
    457			goto done;
    458		} else if (type == NFNL_MSG_BATCH_END) {
    459			status |= NFNL_BATCH_DONE;
    460			goto done;
    461		} else if (type < NLMSG_MIN_TYPE) {
    462			err = -EINVAL;
    463			goto ack;
    464		}
    465
    466		/* We only accept a batch with messages for the same
    467		 * subsystem.
    468		 */
    469		if (NFNL_SUBSYS_ID(type) != subsys_id) {
    470			err = -EINVAL;
    471			goto ack;
    472		}
    473
    474		nc = nfnetlink_find_client(type, ss);
    475		if (!nc) {
    476			err = -EINVAL;
    477			goto ack;
    478		}
    479
    480		if (nc->type != NFNL_CB_BATCH) {
    481			err = -EINVAL;
    482			goto ack;
    483		}
    484
    485		{
    486			int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
    487			struct nfnl_net *nfnlnet = nfnl_pernet(net);
    488			struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
    489			struct nlattr *attr = (void *)nlh + min_len;
    490			u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
    491			int attrlen = nlh->nlmsg_len - min_len;
    492			struct nfnl_info info = {
    493				.net	= net,
    494				.sk	= nfnlnet->nfnl,
    495				.nlh	= nlh,
    496				.nfmsg	= nlmsg_data(nlh),
    497				.extack	= &extack,
    498			};
    499
    500			/* Sanity-check NFTA_MAX_ATTR */
    501			if (ss->cb[cb_id].attr_count > NFNL_MAX_ATTR_COUNT) {
    502				err = -ENOMEM;
    503				goto ack;
    504			}
    505
    506			err = nla_parse_deprecated(cda,
    507						   ss->cb[cb_id].attr_count,
    508						   attr, attrlen,
    509						   ss->cb[cb_id].policy, NULL);
    510			if (err < 0)
    511				goto ack;
    512
    513			err = nc->call(skb, &info, (const struct nlattr **)cda);
    514
    515			/* The lock was released to autoload some module, we
    516			 * have to abort and start from scratch using the
    517			 * original skb.
    518			 */
    519			if (err == -EAGAIN) {
    520				status |= NFNL_BATCH_REPLAY;
    521				goto done;
    522			}
    523		}
    524ack:
    525		if (nlh->nlmsg_flags & NLM_F_ACK || err) {
    526			/* Errors are delivered once the full batch has been
    527			 * processed, this avoids that the same error is
    528			 * reported several times when replaying the batch.
    529			 */
    530			if (nfnl_err_add(&err_list, nlh, err, &extack) < 0) {
    531				/* We failed to enqueue an error, reset the
    532				 * list of errors and send OOM to userspace
    533				 * pointing to the batch header.
    534				 */
    535				nfnl_err_reset(&err_list);
    536				netlink_ack(oskb, nlmsg_hdr(oskb), -ENOMEM,
    537					    NULL);
    538				status |= NFNL_BATCH_FAILURE;
    539				goto done;
    540			}
    541			/* We don't stop processing the batch on errors, thus,
    542			 * userspace gets all the errors that the batch
    543			 * triggers.
    544			 */
    545			if (err)
    546				status |= NFNL_BATCH_FAILURE;
    547		}
    548
    549		msglen = NLMSG_ALIGN(nlh->nlmsg_len);
    550		if (msglen > skb->len)
    551			msglen = skb->len;
    552		skb_pull(skb, msglen);
    553	}
    554done:
    555	if (status & NFNL_BATCH_REPLAY) {
    556		ss->abort(net, oskb, NFNL_ABORT_AUTOLOAD);
    557		nfnl_err_reset(&err_list);
    558		kfree_skb(skb);
    559		module_put(ss->owner);
    560		goto replay;
    561	} else if (status == NFNL_BATCH_DONE) {
    562		err = ss->commit(net, oskb);
    563		if (err == -EAGAIN) {
    564			status |= NFNL_BATCH_REPLAY;
    565			goto done;
    566		} else if (err) {
    567			ss->abort(net, oskb, NFNL_ABORT_NONE);
    568			netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL);
    569		}
    570	} else {
    571		enum nfnl_abort_action abort_action;
    572
    573		if (status & NFNL_BATCH_FAILURE)
    574			abort_action = NFNL_ABORT_NONE;
    575		else
    576			abort_action = NFNL_ABORT_VALIDATE;
    577
    578		err = ss->abort(net, oskb, abort_action);
    579		if (err == -EAGAIN) {
    580			nfnl_err_reset(&err_list);
    581			kfree_skb(skb);
    582			module_put(ss->owner);
    583			status |= NFNL_BATCH_FAILURE;
    584			goto replay_abort;
    585		}
    586	}
    587	if (ss->cleanup)
    588		ss->cleanup(net);
    589
    590	nfnl_err_deliver(&err_list, oskb);
    591	kfree_skb(skb);
    592	module_put(ss->owner);
    593}
    594
    595static const struct nla_policy nfnl_batch_policy[NFNL_BATCH_MAX + 1] = {
    596	[NFNL_BATCH_GENID]	= { .type = NLA_U32 },
    597};
    598
    599static void nfnetlink_rcv_skb_batch(struct sk_buff *skb, struct nlmsghdr *nlh)
    600{
    601	int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
    602	struct nlattr *attr = (void *)nlh + min_len;
    603	struct nlattr *cda[NFNL_BATCH_MAX + 1];
    604	int attrlen = nlh->nlmsg_len - min_len;
    605	struct nfgenmsg *nfgenmsg;
    606	int msglen, err;
    607	u32 gen_id = 0;
    608	u16 res_id;
    609
    610	msglen = NLMSG_ALIGN(nlh->nlmsg_len);
    611	if (msglen > skb->len)
    612		msglen = skb->len;
    613
    614	if (skb->len < NLMSG_HDRLEN + sizeof(struct nfgenmsg))
    615		return;
    616
    617	err = nla_parse_deprecated(cda, NFNL_BATCH_MAX, attr, attrlen,
    618				   nfnl_batch_policy, NULL);
    619	if (err < 0) {
    620		netlink_ack(skb, nlh, err, NULL);
    621		return;
    622	}
    623	if (cda[NFNL_BATCH_GENID])
    624		gen_id = ntohl(nla_get_be32(cda[NFNL_BATCH_GENID]));
    625
    626	nfgenmsg = nlmsg_data(nlh);
    627	skb_pull(skb, msglen);
    628	/* Work around old nft using host byte order */
    629	if (nfgenmsg->res_id == NFNL_SUBSYS_NFTABLES)
    630		res_id = NFNL_SUBSYS_NFTABLES;
    631	else
    632		res_id = ntohs(nfgenmsg->res_id);
    633
    634	nfnetlink_rcv_batch(skb, nlh, res_id, gen_id);
    635}
    636
    637static void nfnetlink_rcv(struct sk_buff *skb)
    638{
    639	struct nlmsghdr *nlh = nlmsg_hdr(skb);
    640
    641	if (skb->len < NLMSG_HDRLEN ||
    642	    nlh->nlmsg_len < NLMSG_HDRLEN ||
    643	    skb->len < nlh->nlmsg_len)
    644		return;
    645
    646	if (!netlink_net_capable(skb, CAP_NET_ADMIN)) {
    647		netlink_ack(skb, nlh, -EPERM, NULL);
    648		return;
    649	}
    650
    651	if (nlh->nlmsg_type == NFNL_MSG_BATCH_BEGIN)
    652		nfnetlink_rcv_skb_batch(skb, nlh);
    653	else
    654		netlink_rcv_skb(skb, nfnetlink_rcv_msg);
    655}
    656
    657static int nfnetlink_bind(struct net *net, int group)
    658{
    659	const struct nfnetlink_subsystem *ss;
    660	int type;
    661
    662	if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
    663		return 0;
    664
    665	type = nfnl_group2type[group];
    666
    667	rcu_read_lock();
    668	ss = nfnetlink_get_subsys(type << 8);
    669	rcu_read_unlock();
    670	if (!ss)
    671		request_module_nowait("nfnetlink-subsys-%d", type);
    672
    673#ifdef CONFIG_NF_CONNTRACK_EVENTS
    674	if (type == NFNL_SUBSYS_CTNETLINK) {
    675		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
    676		WRITE_ONCE(net->ct.ctnetlink_has_listener, true);
    677		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
    678	}
    679#endif
    680	return 0;
    681}
    682
    683static void nfnetlink_unbind(struct net *net, int group)
    684{
    685#ifdef CONFIG_NF_CONNTRACK_EVENTS
    686	if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
    687		return;
    688
    689	if (nfnl_group2type[group] == NFNL_SUBSYS_CTNETLINK) {
    690		nfnl_lock(NFNL_SUBSYS_CTNETLINK);
    691		if (!nfnetlink_has_listeners(net, group))
    692			WRITE_ONCE(net->ct.ctnetlink_has_listener, false);
    693		nfnl_unlock(NFNL_SUBSYS_CTNETLINK);
    694	}
    695#endif
    696}
    697
    698static int __net_init nfnetlink_net_init(struct net *net)
    699{
    700	struct nfnl_net *nfnlnet = nfnl_pernet(net);
    701	struct netlink_kernel_cfg cfg = {
    702		.groups	= NFNLGRP_MAX,
    703		.input	= nfnetlink_rcv,
    704		.bind	= nfnetlink_bind,
    705		.unbind	= nfnetlink_unbind,
    706	};
    707
    708	nfnlnet->nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, &cfg);
    709	if (!nfnlnet->nfnl)
    710		return -ENOMEM;
    711	return 0;
    712}
    713
    714static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list)
    715{
    716	struct nfnl_net *nfnlnet;
    717	struct net *net;
    718
    719	list_for_each_entry(net, net_exit_list, exit_list) {
    720		nfnlnet = nfnl_pernet(net);
    721
    722		netlink_kernel_release(nfnlnet->nfnl);
    723	}
    724}
    725
    726static struct pernet_operations nfnetlink_net_ops = {
    727	.init		= nfnetlink_net_init,
    728	.exit_batch	= nfnetlink_net_exit_batch,
    729	.id		= &nfnetlink_pernet_id,
    730	.size		= sizeof(struct nfnl_net),
    731};
    732
    733static int __init nfnetlink_init(void)
    734{
    735	int i;
    736
    737	for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
    738		BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
    739
    740	for (i=0; i<NFNL_SUBSYS_COUNT; i++)
    741		__mutex_init(&table[i].mutex, nfnl_lockdep_names[i], &nfnl_lockdep_keys[i]);
    742
    743	return register_pernet_subsys(&nfnetlink_net_ops);
    744}
    745
    746static void __exit nfnetlink_exit(void)
    747{
    748	unregister_pernet_subsys(&nfnetlink_net_ops);
    749}
    750module_init(nfnetlink_init);
    751module_exit(nfnetlink_exit);