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

ip6_tables.c (47751B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Packet matching code.
      4 *
      5 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
      6 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
      7 * Copyright (c) 2006-2010 Patrick McHardy <kaber@trash.net>
      8 */
      9
     10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     11
     12#include <linux/kernel.h>
     13#include <linux/capability.h>
     14#include <linux/in.h>
     15#include <linux/skbuff.h>
     16#include <linux/kmod.h>
     17#include <linux/vmalloc.h>
     18#include <linux/netdevice.h>
     19#include <linux/module.h>
     20#include <linux/poison.h>
     21#include <linux/icmpv6.h>
     22#include <net/ipv6.h>
     23#include <net/compat.h>
     24#include <linux/uaccess.h>
     25#include <linux/mutex.h>
     26#include <linux/proc_fs.h>
     27#include <linux/err.h>
     28#include <linux/cpumask.h>
     29
     30#include <linux/netfilter_ipv6/ip6_tables.h>
     31#include <linux/netfilter/x_tables.h>
     32#include <net/netfilter/nf_log.h>
     33#include "../../netfilter/xt_repldata.h"
     34
     35MODULE_LICENSE("GPL");
     36MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
     37MODULE_DESCRIPTION("IPv6 packet filter");
     38MODULE_ALIAS("ip6t_icmp6");
     39
     40void *ip6t_alloc_initial_table(const struct xt_table *info)
     41{
     42	return xt_alloc_initial_table(ip6t, IP6T);
     43}
     44EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);
     45
     46/* Returns whether matches rule or not. */
     47/* Performance critical - called for every packet */
     48static inline bool
     49ip6_packet_match(const struct sk_buff *skb,
     50		 const char *indev,
     51		 const char *outdev,
     52		 const struct ip6t_ip6 *ip6info,
     53		 unsigned int *protoff,
     54		 u16 *fragoff, bool *hotdrop)
     55{
     56	unsigned long ret;
     57	const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
     58
     59	if (NF_INVF(ip6info, IP6T_INV_SRCIP,
     60		    ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk,
     61					 &ip6info->src)) ||
     62	    NF_INVF(ip6info, IP6T_INV_DSTIP,
     63		    ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk,
     64					 &ip6info->dst)))
     65		return false;
     66
     67	ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask);
     68
     69	if (NF_INVF(ip6info, IP6T_INV_VIA_IN, ret != 0))
     70		return false;
     71
     72	ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask);
     73
     74	if (NF_INVF(ip6info, IP6T_INV_VIA_OUT, ret != 0))
     75		return false;
     76
     77/* ... might want to do something with class and flowlabel here ... */
     78
     79	/* look for the desired protocol header */
     80	if (ip6info->flags & IP6T_F_PROTO) {
     81		int protohdr;
     82		unsigned short _frag_off;
     83
     84		protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off, NULL);
     85		if (protohdr < 0) {
     86			if (_frag_off == 0)
     87				*hotdrop = true;
     88			return false;
     89		}
     90		*fragoff = _frag_off;
     91
     92		if (ip6info->proto == protohdr) {
     93			if (ip6info->invflags & IP6T_INV_PROTO)
     94				return false;
     95
     96			return true;
     97		}
     98
     99		/* We need match for the '-p all', too! */
    100		if ((ip6info->proto != 0) &&
    101			!(ip6info->invflags & IP6T_INV_PROTO))
    102			return false;
    103	}
    104	return true;
    105}
    106
    107/* should be ip6 safe */
    108static bool
    109ip6_checkentry(const struct ip6t_ip6 *ipv6)
    110{
    111	if (ipv6->flags & ~IP6T_F_MASK)
    112		return false;
    113	if (ipv6->invflags & ~IP6T_INV_MASK)
    114		return false;
    115
    116	return true;
    117}
    118
    119static unsigned int
    120ip6t_error(struct sk_buff *skb, const struct xt_action_param *par)
    121{
    122	net_info_ratelimited("error: `%s'\n", (const char *)par->targinfo);
    123
    124	return NF_DROP;
    125}
    126
    127static inline struct ip6t_entry *
    128get_entry(const void *base, unsigned int offset)
    129{
    130	return (struct ip6t_entry *)(base + offset);
    131}
    132
    133/* All zeroes == unconditional rule. */
    134/* Mildly perf critical (only if packet tracing is on) */
    135static inline bool unconditional(const struct ip6t_entry *e)
    136{
    137	static const struct ip6t_ip6 uncond;
    138
    139	return e->target_offset == sizeof(struct ip6t_entry) &&
    140	       memcmp(&e->ipv6, &uncond, sizeof(uncond)) == 0;
    141}
    142
    143static inline const struct xt_entry_target *
    144ip6t_get_target_c(const struct ip6t_entry *e)
    145{
    146	return ip6t_get_target((struct ip6t_entry *)e);
    147}
    148
    149#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
    150/* This cries for unification! */
    151static const char *const hooknames[] = {
    152	[NF_INET_PRE_ROUTING]		= "PREROUTING",
    153	[NF_INET_LOCAL_IN]		= "INPUT",
    154	[NF_INET_FORWARD]		= "FORWARD",
    155	[NF_INET_LOCAL_OUT]		= "OUTPUT",
    156	[NF_INET_POST_ROUTING]		= "POSTROUTING",
    157};
    158
    159enum nf_ip_trace_comments {
    160	NF_IP6_TRACE_COMMENT_RULE,
    161	NF_IP6_TRACE_COMMENT_RETURN,
    162	NF_IP6_TRACE_COMMENT_POLICY,
    163};
    164
    165static const char *const comments[] = {
    166	[NF_IP6_TRACE_COMMENT_RULE]	= "rule",
    167	[NF_IP6_TRACE_COMMENT_RETURN]	= "return",
    168	[NF_IP6_TRACE_COMMENT_POLICY]	= "policy",
    169};
    170
    171static const struct nf_loginfo trace_loginfo = {
    172	.type = NF_LOG_TYPE_LOG,
    173	.u = {
    174		.log = {
    175			.level = LOGLEVEL_WARNING,
    176			.logflags = NF_LOG_DEFAULT_MASK,
    177		},
    178	},
    179};
    180
    181/* Mildly perf critical (only if packet tracing is on) */
    182static inline int
    183get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
    184		      const char *hookname, const char **chainname,
    185		      const char **comment, unsigned int *rulenum)
    186{
    187	const struct xt_standard_target *t = (void *)ip6t_get_target_c(s);
    188
    189	if (strcmp(t->target.u.kernel.target->name, XT_ERROR_TARGET) == 0) {
    190		/* Head of user chain: ERROR target with chainname */
    191		*chainname = t->target.data;
    192		(*rulenum) = 0;
    193	} else if (s == e) {
    194		(*rulenum)++;
    195
    196		if (unconditional(s) &&
    197		    strcmp(t->target.u.kernel.target->name,
    198			   XT_STANDARD_TARGET) == 0 &&
    199		    t->verdict < 0) {
    200			/* Tail of chains: STANDARD target (return/policy) */
    201			*comment = *chainname == hookname
    202				? comments[NF_IP6_TRACE_COMMENT_POLICY]
    203				: comments[NF_IP6_TRACE_COMMENT_RETURN];
    204		}
    205		return 1;
    206	} else
    207		(*rulenum)++;
    208
    209	return 0;
    210}
    211
    212static void trace_packet(struct net *net,
    213			 const struct sk_buff *skb,
    214			 unsigned int hook,
    215			 const struct net_device *in,
    216			 const struct net_device *out,
    217			 const char *tablename,
    218			 const struct xt_table_info *private,
    219			 const struct ip6t_entry *e)
    220{
    221	const struct ip6t_entry *root;
    222	const char *hookname, *chainname, *comment;
    223	const struct ip6t_entry *iter;
    224	unsigned int rulenum = 0;
    225
    226	root = get_entry(private->entries, private->hook_entry[hook]);
    227
    228	hookname = chainname = hooknames[hook];
    229	comment = comments[NF_IP6_TRACE_COMMENT_RULE];
    230
    231	xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
    232		if (get_chainname_rulenum(iter, e, hookname,
    233		    &chainname, &comment, &rulenum) != 0)
    234			break;
    235
    236	nf_log_trace(net, AF_INET6, hook, skb, in, out, &trace_loginfo,
    237		     "TRACE: %s:%s:%s:%u ",
    238		     tablename, chainname, comment, rulenum);
    239}
    240#endif
    241
    242static inline struct ip6t_entry *
    243ip6t_next_entry(const struct ip6t_entry *entry)
    244{
    245	return (void *)entry + entry->next_offset;
    246}
    247
    248/* Returns one of the generic firewall policies, like NF_ACCEPT. */
    249unsigned int
    250ip6t_do_table(void *priv, struct sk_buff *skb,
    251	      const struct nf_hook_state *state)
    252{
    253	const struct xt_table *table = priv;
    254	unsigned int hook = state->hook;
    255	static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
    256	/* Initializing verdict to NF_DROP keeps gcc happy. */
    257	unsigned int verdict = NF_DROP;
    258	const char *indev, *outdev;
    259	const void *table_base;
    260	struct ip6t_entry *e, **jumpstack;
    261	unsigned int stackidx, cpu;
    262	const struct xt_table_info *private;
    263	struct xt_action_param acpar;
    264	unsigned int addend;
    265
    266	/* Initialization */
    267	stackidx = 0;
    268	indev = state->in ? state->in->name : nulldevname;
    269	outdev = state->out ? state->out->name : nulldevname;
    270	/* We handle fragments by dealing with the first fragment as
    271	 * if it was a normal packet.  All other fragments are treated
    272	 * normally, except that they will NEVER match rules that ask
    273	 * things we don't know, ie. tcp syn flag or ports).  If the
    274	 * rule is also a fragment-specific rule, non-fragments won't
    275	 * match it. */
    276	acpar.fragoff = 0;
    277	acpar.hotdrop = false;
    278	acpar.state   = state;
    279
    280	WARN_ON(!(table->valid_hooks & (1 << hook)));
    281
    282	local_bh_disable();
    283	addend = xt_write_recseq_begin();
    284	private = READ_ONCE(table->private); /* Address dependency. */
    285	cpu        = smp_processor_id();
    286	table_base = private->entries;
    287	jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];
    288
    289	/* Switch to alternate jumpstack if we're being invoked via TEE.
    290	 * TEE issues XT_CONTINUE verdict on original skb so we must not
    291	 * clobber the jumpstack.
    292	 *
    293	 * For recursion via REJECT or SYNPROXY the stack will be clobbered
    294	 * but it is no problem since absolute verdict is issued by these.
    295	 */
    296	if (static_key_false(&xt_tee_enabled))
    297		jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated);
    298
    299	e = get_entry(table_base, private->hook_entry[hook]);
    300
    301	do {
    302		const struct xt_entry_target *t;
    303		const struct xt_entry_match *ematch;
    304		struct xt_counters *counter;
    305
    306		WARN_ON(!e);
    307		acpar.thoff = 0;
    308		if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
    309		    &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) {
    310 no_match:
    311			e = ip6t_next_entry(e);
    312			continue;
    313		}
    314
    315		xt_ematch_foreach(ematch, e) {
    316			acpar.match     = ematch->u.kernel.match;
    317			acpar.matchinfo = ematch->data;
    318			if (!acpar.match->match(skb, &acpar))
    319				goto no_match;
    320		}
    321
    322		counter = xt_get_this_cpu_counter(&e->counters);
    323		ADD_COUNTER(*counter, skb->len, 1);
    324
    325		t = ip6t_get_target_c(e);
    326		WARN_ON(!t->u.kernel.target);
    327
    328#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
    329		/* The packet is traced: log it */
    330		if (unlikely(skb->nf_trace))
    331			trace_packet(state->net, skb, hook, state->in,
    332				     state->out, table->name, private, e);
    333#endif
    334		/* Standard target? */
    335		if (!t->u.kernel.target->target) {
    336			int v;
    337
    338			v = ((struct xt_standard_target *)t)->verdict;
    339			if (v < 0) {
    340				/* Pop from stack? */
    341				if (v != XT_RETURN) {
    342					verdict = (unsigned int)(-v) - 1;
    343					break;
    344				}
    345				if (stackidx == 0)
    346					e = get_entry(table_base,
    347					    private->underflow[hook]);
    348				else
    349					e = ip6t_next_entry(jumpstack[--stackidx]);
    350				continue;
    351			}
    352			if (table_base + v != ip6t_next_entry(e) &&
    353			    !(e->ipv6.flags & IP6T_F_GOTO)) {
    354				if (unlikely(stackidx >= private->stacksize)) {
    355					verdict = NF_DROP;
    356					break;
    357				}
    358				jumpstack[stackidx++] = e;
    359			}
    360
    361			e = get_entry(table_base, v);
    362			continue;
    363		}
    364
    365		acpar.target   = t->u.kernel.target;
    366		acpar.targinfo = t->data;
    367
    368		verdict = t->u.kernel.target->target(skb, &acpar);
    369		if (verdict == XT_CONTINUE)
    370			e = ip6t_next_entry(e);
    371		else
    372			/* Verdict */
    373			break;
    374	} while (!acpar.hotdrop);
    375
    376	xt_write_recseq_end(addend);
    377	local_bh_enable();
    378
    379	if (acpar.hotdrop)
    380		return NF_DROP;
    381	else return verdict;
    382}
    383
    384/* Figures out from what hook each rule can be called: returns 0 if
    385   there are loops.  Puts hook bitmask in comefrom. */
    386static int
    387mark_source_chains(const struct xt_table_info *newinfo,
    388		   unsigned int valid_hooks, void *entry0,
    389		   unsigned int *offsets)
    390{
    391	unsigned int hook;
    392
    393	/* No recursion; use packet counter to save back ptrs (reset
    394	   to 0 as we leave), and comefrom to save source hook bitmask */
    395	for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
    396		unsigned int pos = newinfo->hook_entry[hook];
    397		struct ip6t_entry *e = entry0 + pos;
    398
    399		if (!(valid_hooks & (1 << hook)))
    400			continue;
    401
    402		/* Set initial back pointer. */
    403		e->counters.pcnt = pos;
    404
    405		for (;;) {
    406			const struct xt_standard_target *t
    407				= (void *)ip6t_get_target_c(e);
    408			int visited = e->comefrom & (1 << hook);
    409
    410			if (e->comefrom & (1 << NF_INET_NUMHOOKS))
    411				return 0;
    412
    413			e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));
    414
    415			/* Unconditional return/END. */
    416			if ((unconditional(e) &&
    417			     (strcmp(t->target.u.user.name,
    418				     XT_STANDARD_TARGET) == 0) &&
    419			     t->verdict < 0) || visited) {
    420				unsigned int oldpos, size;
    421
    422				/* Return: backtrack through the last
    423				   big jump. */
    424				do {
    425					e->comefrom ^= (1<<NF_INET_NUMHOOKS);
    426					oldpos = pos;
    427					pos = e->counters.pcnt;
    428					e->counters.pcnt = 0;
    429
    430					/* We're at the start. */
    431					if (pos == oldpos)
    432						goto next;
    433
    434					e = entry0 + pos;
    435				} while (oldpos == pos + e->next_offset);
    436
    437				/* Move along one */
    438				size = e->next_offset;
    439				e = entry0 + pos + size;
    440				if (pos + size >= newinfo->size)
    441					return 0;
    442				e->counters.pcnt = pos;
    443				pos += size;
    444			} else {
    445				int newpos = t->verdict;
    446
    447				if (strcmp(t->target.u.user.name,
    448					   XT_STANDARD_TARGET) == 0 &&
    449				    newpos >= 0) {
    450					/* This a jump; chase it. */
    451					if (!xt_find_jump_offset(offsets, newpos,
    452								 newinfo->number))
    453						return 0;
    454				} else {
    455					/* ... this is a fallthru */
    456					newpos = pos + e->next_offset;
    457					if (newpos >= newinfo->size)
    458						return 0;
    459				}
    460				e = entry0 + newpos;
    461				e->counters.pcnt = pos;
    462				pos = newpos;
    463			}
    464		}
    465next:		;
    466	}
    467	return 1;
    468}
    469
    470static void cleanup_match(struct xt_entry_match *m, struct net *net)
    471{
    472	struct xt_mtdtor_param par;
    473
    474	par.net       = net;
    475	par.match     = m->u.kernel.match;
    476	par.matchinfo = m->data;
    477	par.family    = NFPROTO_IPV6;
    478	if (par.match->destroy != NULL)
    479		par.match->destroy(&par);
    480	module_put(par.match->me);
    481}
    482
    483static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
    484{
    485	const struct ip6t_ip6 *ipv6 = par->entryinfo;
    486
    487	par->match     = m->u.kernel.match;
    488	par->matchinfo = m->data;
    489
    490	return xt_check_match(par, m->u.match_size - sizeof(*m),
    491			      ipv6->proto, ipv6->invflags & IP6T_INV_PROTO);
    492}
    493
    494static int
    495find_check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
    496{
    497	struct xt_match *match;
    498	int ret;
    499
    500	match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name,
    501				      m->u.user.revision);
    502	if (IS_ERR(match))
    503		return PTR_ERR(match);
    504
    505	m->u.kernel.match = match;
    506
    507	ret = check_match(m, par);
    508	if (ret)
    509		goto err;
    510
    511	return 0;
    512err:
    513	module_put(m->u.kernel.match->me);
    514	return ret;
    515}
    516
    517static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
    518{
    519	struct xt_entry_target *t = ip6t_get_target(e);
    520	struct xt_tgchk_param par = {
    521		.net       = net,
    522		.table     = name,
    523		.entryinfo = e,
    524		.target    = t->u.kernel.target,
    525		.targinfo  = t->data,
    526		.hook_mask = e->comefrom,
    527		.family    = NFPROTO_IPV6,
    528	};
    529
    530	return xt_check_target(&par, t->u.target_size - sizeof(*t),
    531			       e->ipv6.proto,
    532			       e->ipv6.invflags & IP6T_INV_PROTO);
    533}
    534
    535static int
    536find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
    537		 unsigned int size,
    538		 struct xt_percpu_counter_alloc_state *alloc_state)
    539{
    540	struct xt_entry_target *t;
    541	struct xt_target *target;
    542	int ret;
    543	unsigned int j;
    544	struct xt_mtchk_param mtpar;
    545	struct xt_entry_match *ematch;
    546
    547	if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
    548		return -ENOMEM;
    549
    550	j = 0;
    551	memset(&mtpar, 0, sizeof(mtpar));
    552	mtpar.net	= net;
    553	mtpar.table     = name;
    554	mtpar.entryinfo = &e->ipv6;
    555	mtpar.hook_mask = e->comefrom;
    556	mtpar.family    = NFPROTO_IPV6;
    557	xt_ematch_foreach(ematch, e) {
    558		ret = find_check_match(ematch, &mtpar);
    559		if (ret != 0)
    560			goto cleanup_matches;
    561		++j;
    562	}
    563
    564	t = ip6t_get_target(e);
    565	target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name,
    566					t->u.user.revision);
    567	if (IS_ERR(target)) {
    568		ret = PTR_ERR(target);
    569		goto cleanup_matches;
    570	}
    571	t->u.kernel.target = target;
    572
    573	ret = check_target(e, net, name);
    574	if (ret)
    575		goto err;
    576	return 0;
    577 err:
    578	module_put(t->u.kernel.target->me);
    579 cleanup_matches:
    580	xt_ematch_foreach(ematch, e) {
    581		if (j-- == 0)
    582			break;
    583		cleanup_match(ematch, net);
    584	}
    585
    586	xt_percpu_counter_free(&e->counters);
    587
    588	return ret;
    589}
    590
    591static bool check_underflow(const struct ip6t_entry *e)
    592{
    593	const struct xt_entry_target *t;
    594	unsigned int verdict;
    595
    596	if (!unconditional(e))
    597		return false;
    598	t = ip6t_get_target_c(e);
    599	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
    600		return false;
    601	verdict = ((struct xt_standard_target *)t)->verdict;
    602	verdict = -verdict - 1;
    603	return verdict == NF_DROP || verdict == NF_ACCEPT;
    604}
    605
    606static int
    607check_entry_size_and_hooks(struct ip6t_entry *e,
    608			   struct xt_table_info *newinfo,
    609			   const unsigned char *base,
    610			   const unsigned char *limit,
    611			   const unsigned int *hook_entries,
    612			   const unsigned int *underflows,
    613			   unsigned int valid_hooks)
    614{
    615	unsigned int h;
    616	int err;
    617
    618	if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 ||
    619	    (unsigned char *)e + sizeof(struct ip6t_entry) >= limit ||
    620	    (unsigned char *)e + e->next_offset > limit)
    621		return -EINVAL;
    622
    623	if (e->next_offset
    624	    < sizeof(struct ip6t_entry) + sizeof(struct xt_entry_target))
    625		return -EINVAL;
    626
    627	if (!ip6_checkentry(&e->ipv6))
    628		return -EINVAL;
    629
    630	err = xt_check_entry_offsets(e, e->elems, e->target_offset,
    631				     e->next_offset);
    632	if (err)
    633		return err;
    634
    635	/* Check hooks & underflows */
    636	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
    637		if (!(valid_hooks & (1 << h)))
    638			continue;
    639		if ((unsigned char *)e - base == hook_entries[h])
    640			newinfo->hook_entry[h] = hook_entries[h];
    641		if ((unsigned char *)e - base == underflows[h]) {
    642			if (!check_underflow(e))
    643				return -EINVAL;
    644
    645			newinfo->underflow[h] = underflows[h];
    646		}
    647	}
    648
    649	/* Clear counters and comefrom */
    650	e->counters = ((struct xt_counters) { 0, 0 });
    651	e->comefrom = 0;
    652	return 0;
    653}
    654
    655static void cleanup_entry(struct ip6t_entry *e, struct net *net)
    656{
    657	struct xt_tgdtor_param par;
    658	struct xt_entry_target *t;
    659	struct xt_entry_match *ematch;
    660
    661	/* Cleanup all matches */
    662	xt_ematch_foreach(ematch, e)
    663		cleanup_match(ematch, net);
    664	t = ip6t_get_target(e);
    665
    666	par.net      = net;
    667	par.target   = t->u.kernel.target;
    668	par.targinfo = t->data;
    669	par.family   = NFPROTO_IPV6;
    670	if (par.target->destroy != NULL)
    671		par.target->destroy(&par);
    672	module_put(par.target->me);
    673	xt_percpu_counter_free(&e->counters);
    674}
    675
    676/* Checks and translates the user-supplied table segment (held in
    677   newinfo) */
    678static int
    679translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
    680		const struct ip6t_replace *repl)
    681{
    682	struct xt_percpu_counter_alloc_state alloc_state = { 0 };
    683	struct ip6t_entry *iter;
    684	unsigned int *offsets;
    685	unsigned int i;
    686	int ret = 0;
    687
    688	newinfo->size = repl->size;
    689	newinfo->number = repl->num_entries;
    690
    691	/* Init all hooks to impossible value. */
    692	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
    693		newinfo->hook_entry[i] = 0xFFFFFFFF;
    694		newinfo->underflow[i] = 0xFFFFFFFF;
    695	}
    696
    697	offsets = xt_alloc_entry_offsets(newinfo->number);
    698	if (!offsets)
    699		return -ENOMEM;
    700	i = 0;
    701	/* Walk through entries, checking offsets. */
    702	xt_entry_foreach(iter, entry0, newinfo->size) {
    703		ret = check_entry_size_and_hooks(iter, newinfo, entry0,
    704						 entry0 + repl->size,
    705						 repl->hook_entry,
    706						 repl->underflow,
    707						 repl->valid_hooks);
    708		if (ret != 0)
    709			goto out_free;
    710		if (i < repl->num_entries)
    711			offsets[i] = (void *)iter - entry0;
    712		++i;
    713		if (strcmp(ip6t_get_target(iter)->u.user.name,
    714		    XT_ERROR_TARGET) == 0)
    715			++newinfo->stacksize;
    716	}
    717
    718	ret = -EINVAL;
    719	if (i != repl->num_entries)
    720		goto out_free;
    721
    722	ret = xt_check_table_hooks(newinfo, repl->valid_hooks);
    723	if (ret)
    724		goto out_free;
    725
    726	if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) {
    727		ret = -ELOOP;
    728		goto out_free;
    729	}
    730	kvfree(offsets);
    731
    732	/* Finally, each sanity check must pass */
    733	i = 0;
    734	xt_entry_foreach(iter, entry0, newinfo->size) {
    735		ret = find_check_entry(iter, net, repl->name, repl->size,
    736				       &alloc_state);
    737		if (ret != 0)
    738			break;
    739		++i;
    740	}
    741
    742	if (ret != 0) {
    743		xt_entry_foreach(iter, entry0, newinfo->size) {
    744			if (i-- == 0)
    745				break;
    746			cleanup_entry(iter, net);
    747		}
    748		return ret;
    749	}
    750
    751	return ret;
    752 out_free:
    753	kvfree(offsets);
    754	return ret;
    755}
    756
    757static void
    758get_counters(const struct xt_table_info *t,
    759	     struct xt_counters counters[])
    760{
    761	struct ip6t_entry *iter;
    762	unsigned int cpu;
    763	unsigned int i;
    764
    765	for_each_possible_cpu(cpu) {
    766		seqcount_t *s = &per_cpu(xt_recseq, cpu);
    767
    768		i = 0;
    769		xt_entry_foreach(iter, t->entries, t->size) {
    770			struct xt_counters *tmp;
    771			u64 bcnt, pcnt;
    772			unsigned int start;
    773
    774			tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
    775			do {
    776				start = read_seqcount_begin(s);
    777				bcnt = tmp->bcnt;
    778				pcnt = tmp->pcnt;
    779			} while (read_seqcount_retry(s, start));
    780
    781			ADD_COUNTER(counters[i], bcnt, pcnt);
    782			++i;
    783			cond_resched();
    784		}
    785	}
    786}
    787
    788static void get_old_counters(const struct xt_table_info *t,
    789			     struct xt_counters counters[])
    790{
    791	struct ip6t_entry *iter;
    792	unsigned int cpu, i;
    793
    794	for_each_possible_cpu(cpu) {
    795		i = 0;
    796		xt_entry_foreach(iter, t->entries, t->size) {
    797			const struct xt_counters *tmp;
    798
    799			tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
    800			ADD_COUNTER(counters[i], tmp->bcnt, tmp->pcnt);
    801			++i;
    802		}
    803		cond_resched();
    804	}
    805}
    806
    807static struct xt_counters *alloc_counters(const struct xt_table *table)
    808{
    809	unsigned int countersize;
    810	struct xt_counters *counters;
    811	const struct xt_table_info *private = table->private;
    812
    813	/* We need atomic snapshot of counters: rest doesn't change
    814	   (other than comefrom, which userspace doesn't care
    815	   about). */
    816	countersize = sizeof(struct xt_counters) * private->number;
    817	counters = vzalloc(countersize);
    818
    819	if (counters == NULL)
    820		return ERR_PTR(-ENOMEM);
    821
    822	get_counters(private, counters);
    823
    824	return counters;
    825}
    826
    827static int
    828copy_entries_to_user(unsigned int total_size,
    829		     const struct xt_table *table,
    830		     void __user *userptr)
    831{
    832	unsigned int off, num;
    833	const struct ip6t_entry *e;
    834	struct xt_counters *counters;
    835	const struct xt_table_info *private = table->private;
    836	int ret = 0;
    837	const void *loc_cpu_entry;
    838
    839	counters = alloc_counters(table);
    840	if (IS_ERR(counters))
    841		return PTR_ERR(counters);
    842
    843	loc_cpu_entry = private->entries;
    844
    845	/* FIXME: use iterator macros --RR */
    846	/* ... then go back and fix counters and names */
    847	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
    848		unsigned int i;
    849		const struct xt_entry_match *m;
    850		const struct xt_entry_target *t;
    851
    852		e = loc_cpu_entry + off;
    853		if (copy_to_user(userptr + off, e, sizeof(*e))) {
    854			ret = -EFAULT;
    855			goto free_counters;
    856		}
    857		if (copy_to_user(userptr + off
    858				 + offsetof(struct ip6t_entry, counters),
    859				 &counters[num],
    860				 sizeof(counters[num])) != 0) {
    861			ret = -EFAULT;
    862			goto free_counters;
    863		}
    864
    865		for (i = sizeof(struct ip6t_entry);
    866		     i < e->target_offset;
    867		     i += m->u.match_size) {
    868			m = (void *)e + i;
    869
    870			if (xt_match_to_user(m, userptr + off + i)) {
    871				ret = -EFAULT;
    872				goto free_counters;
    873			}
    874		}
    875
    876		t = ip6t_get_target_c(e);
    877		if (xt_target_to_user(t, userptr + off + e->target_offset)) {
    878			ret = -EFAULT;
    879			goto free_counters;
    880		}
    881	}
    882
    883 free_counters:
    884	vfree(counters);
    885	return ret;
    886}
    887
    888#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
    889static void compat_standard_from_user(void *dst, const void *src)
    890{
    891	int v = *(compat_int_t *)src;
    892
    893	if (v > 0)
    894		v += xt_compat_calc_jump(AF_INET6, v);
    895	memcpy(dst, &v, sizeof(v));
    896}
    897
    898static int compat_standard_to_user(void __user *dst, const void *src)
    899{
    900	compat_int_t cv = *(int *)src;
    901
    902	if (cv > 0)
    903		cv -= xt_compat_calc_jump(AF_INET6, cv);
    904	return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
    905}
    906
    907static int compat_calc_entry(const struct ip6t_entry *e,
    908			     const struct xt_table_info *info,
    909			     const void *base, struct xt_table_info *newinfo)
    910{
    911	const struct xt_entry_match *ematch;
    912	const struct xt_entry_target *t;
    913	unsigned int entry_offset;
    914	int off, i, ret;
    915
    916	off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
    917	entry_offset = (void *)e - base;
    918	xt_ematch_foreach(ematch, e)
    919		off += xt_compat_match_offset(ematch->u.kernel.match);
    920	t = ip6t_get_target_c(e);
    921	off += xt_compat_target_offset(t->u.kernel.target);
    922	newinfo->size -= off;
    923	ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
    924	if (ret)
    925		return ret;
    926
    927	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
    928		if (info->hook_entry[i] &&
    929		    (e < (struct ip6t_entry *)(base + info->hook_entry[i])))
    930			newinfo->hook_entry[i] -= off;
    931		if (info->underflow[i] &&
    932		    (e < (struct ip6t_entry *)(base + info->underflow[i])))
    933			newinfo->underflow[i] -= off;
    934	}
    935	return 0;
    936}
    937
    938static int compat_table_info(const struct xt_table_info *info,
    939			     struct xt_table_info *newinfo)
    940{
    941	struct ip6t_entry *iter;
    942	const void *loc_cpu_entry;
    943	int ret;
    944
    945	if (!newinfo || !info)
    946		return -EINVAL;
    947
    948	/* we dont care about newinfo->entries */
    949	memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
    950	newinfo->initial_entries = 0;
    951	loc_cpu_entry = info->entries;
    952	ret = xt_compat_init_offsets(AF_INET6, info->number);
    953	if (ret)
    954		return ret;
    955	xt_entry_foreach(iter, loc_cpu_entry, info->size) {
    956		ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
    957		if (ret != 0)
    958			return ret;
    959	}
    960	return 0;
    961}
    962#endif
    963
    964static int get_info(struct net *net, void __user *user, const int *len)
    965{
    966	char name[XT_TABLE_MAXNAMELEN];
    967	struct xt_table *t;
    968	int ret;
    969
    970	if (*len != sizeof(struct ip6t_getinfo))
    971		return -EINVAL;
    972
    973	if (copy_from_user(name, user, sizeof(name)) != 0)
    974		return -EFAULT;
    975
    976	name[XT_TABLE_MAXNAMELEN-1] = '\0';
    977#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
    978	if (in_compat_syscall())
    979		xt_compat_lock(AF_INET6);
    980#endif
    981	t = xt_request_find_table_lock(net, AF_INET6, name);
    982	if (!IS_ERR(t)) {
    983		struct ip6t_getinfo info;
    984		const struct xt_table_info *private = t->private;
    985#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
    986		struct xt_table_info tmp;
    987
    988		if (in_compat_syscall()) {
    989			ret = compat_table_info(private, &tmp);
    990			xt_compat_flush_offsets(AF_INET6);
    991			private = &tmp;
    992		}
    993#endif
    994		memset(&info, 0, sizeof(info));
    995		info.valid_hooks = t->valid_hooks;
    996		memcpy(info.hook_entry, private->hook_entry,
    997		       sizeof(info.hook_entry));
    998		memcpy(info.underflow, private->underflow,
    999		       sizeof(info.underflow));
   1000		info.num_entries = private->number;
   1001		info.size = private->size;
   1002		strcpy(info.name, name);
   1003
   1004		if (copy_to_user(user, &info, *len) != 0)
   1005			ret = -EFAULT;
   1006		else
   1007			ret = 0;
   1008
   1009		xt_table_unlock(t);
   1010		module_put(t->me);
   1011	} else
   1012		ret = PTR_ERR(t);
   1013#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
   1014	if (in_compat_syscall())
   1015		xt_compat_unlock(AF_INET6);
   1016#endif
   1017	return ret;
   1018}
   1019
   1020static int
   1021get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
   1022	    const int *len)
   1023{
   1024	int ret;
   1025	struct ip6t_get_entries get;
   1026	struct xt_table *t;
   1027
   1028	if (*len < sizeof(get))
   1029		return -EINVAL;
   1030	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
   1031		return -EFAULT;
   1032	if (*len != sizeof(struct ip6t_get_entries) + get.size)
   1033		return -EINVAL;
   1034
   1035	get.name[sizeof(get.name) - 1] = '\0';
   1036
   1037	t = xt_find_table_lock(net, AF_INET6, get.name);
   1038	if (!IS_ERR(t)) {
   1039		struct xt_table_info *private = t->private;
   1040		if (get.size == private->size)
   1041			ret = copy_entries_to_user(private->size,
   1042						   t, uptr->entrytable);
   1043		else
   1044			ret = -EAGAIN;
   1045
   1046		module_put(t->me);
   1047		xt_table_unlock(t);
   1048	} else
   1049		ret = PTR_ERR(t);
   1050
   1051	return ret;
   1052}
   1053
   1054static int
   1055__do_replace(struct net *net, const char *name, unsigned int valid_hooks,
   1056	     struct xt_table_info *newinfo, unsigned int num_counters,
   1057	     void __user *counters_ptr)
   1058{
   1059	int ret;
   1060	struct xt_table *t;
   1061	struct xt_table_info *oldinfo;
   1062	struct xt_counters *counters;
   1063	struct ip6t_entry *iter;
   1064
   1065	ret = 0;
   1066	counters = xt_counters_alloc(num_counters);
   1067	if (!counters) {
   1068		ret = -ENOMEM;
   1069		goto out;
   1070	}
   1071
   1072	t = xt_request_find_table_lock(net, AF_INET6, name);
   1073	if (IS_ERR(t)) {
   1074		ret = PTR_ERR(t);
   1075		goto free_newinfo_counters_untrans;
   1076	}
   1077
   1078	/* You lied! */
   1079	if (valid_hooks != t->valid_hooks) {
   1080		ret = -EINVAL;
   1081		goto put_module;
   1082	}
   1083
   1084	oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
   1085	if (!oldinfo)
   1086		goto put_module;
   1087
   1088	/* Update module usage count based on number of rules */
   1089	if ((oldinfo->number > oldinfo->initial_entries) ||
   1090	    (newinfo->number <= oldinfo->initial_entries))
   1091		module_put(t->me);
   1092	if ((oldinfo->number > oldinfo->initial_entries) &&
   1093	    (newinfo->number <= oldinfo->initial_entries))
   1094		module_put(t->me);
   1095
   1096	xt_table_unlock(t);
   1097
   1098	get_old_counters(oldinfo, counters);
   1099
   1100	/* Decrease module usage counts and free resource */
   1101	xt_entry_foreach(iter, oldinfo->entries, oldinfo->size)
   1102		cleanup_entry(iter, net);
   1103
   1104	xt_free_table_info(oldinfo);
   1105	if (copy_to_user(counters_ptr, counters,
   1106			 sizeof(struct xt_counters) * num_counters) != 0) {
   1107		/* Silent error, can't fail, new table is already in place */
   1108		net_warn_ratelimited("ip6tables: counters copy to user failed while replacing table\n");
   1109	}
   1110	vfree(counters);
   1111	return ret;
   1112
   1113 put_module:
   1114	module_put(t->me);
   1115	xt_table_unlock(t);
   1116 free_newinfo_counters_untrans:
   1117	vfree(counters);
   1118 out:
   1119	return ret;
   1120}
   1121
   1122static int
   1123do_replace(struct net *net, sockptr_t arg, unsigned int len)
   1124{
   1125	int ret;
   1126	struct ip6t_replace tmp;
   1127	struct xt_table_info *newinfo;
   1128	void *loc_cpu_entry;
   1129	struct ip6t_entry *iter;
   1130
   1131	if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
   1132		return -EFAULT;
   1133
   1134	/* overflow check */
   1135	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
   1136		return -ENOMEM;
   1137	if (tmp.num_counters == 0)
   1138		return -EINVAL;
   1139
   1140	tmp.name[sizeof(tmp.name)-1] = 0;
   1141
   1142	newinfo = xt_alloc_table_info(tmp.size);
   1143	if (!newinfo)
   1144		return -ENOMEM;
   1145
   1146	loc_cpu_entry = newinfo->entries;
   1147	if (copy_from_sockptr_offset(loc_cpu_entry, arg, sizeof(tmp),
   1148			tmp.size) != 0) {
   1149		ret = -EFAULT;
   1150		goto free_newinfo;
   1151	}
   1152
   1153	ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
   1154	if (ret != 0)
   1155		goto free_newinfo;
   1156
   1157	ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
   1158			   tmp.num_counters, tmp.counters);
   1159	if (ret)
   1160		goto free_newinfo_untrans;
   1161	return 0;
   1162
   1163 free_newinfo_untrans:
   1164	xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
   1165		cleanup_entry(iter, net);
   1166 free_newinfo:
   1167	xt_free_table_info(newinfo);
   1168	return ret;
   1169}
   1170
   1171static int
   1172do_add_counters(struct net *net, sockptr_t arg, unsigned int len)
   1173{
   1174	unsigned int i;
   1175	struct xt_counters_info tmp;
   1176	struct xt_counters *paddc;
   1177	struct xt_table *t;
   1178	const struct xt_table_info *private;
   1179	int ret = 0;
   1180	struct ip6t_entry *iter;
   1181	unsigned int addend;
   1182
   1183	paddc = xt_copy_counters(arg, len, &tmp);
   1184	if (IS_ERR(paddc))
   1185		return PTR_ERR(paddc);
   1186	t = xt_find_table_lock(net, AF_INET6, tmp.name);
   1187	if (IS_ERR(t)) {
   1188		ret = PTR_ERR(t);
   1189		goto free;
   1190	}
   1191
   1192	local_bh_disable();
   1193	private = t->private;
   1194	if (private->number != tmp.num_counters) {
   1195		ret = -EINVAL;
   1196		goto unlock_up_free;
   1197	}
   1198
   1199	i = 0;
   1200	addend = xt_write_recseq_begin();
   1201	xt_entry_foreach(iter, private->entries, private->size) {
   1202		struct xt_counters *tmp;
   1203
   1204		tmp = xt_get_this_cpu_counter(&iter->counters);
   1205		ADD_COUNTER(*tmp, paddc[i].bcnt, paddc[i].pcnt);
   1206		++i;
   1207	}
   1208	xt_write_recseq_end(addend);
   1209 unlock_up_free:
   1210	local_bh_enable();
   1211	xt_table_unlock(t);
   1212	module_put(t->me);
   1213 free:
   1214	vfree(paddc);
   1215
   1216	return ret;
   1217}
   1218
   1219#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
   1220struct compat_ip6t_replace {
   1221	char			name[XT_TABLE_MAXNAMELEN];
   1222	u32			valid_hooks;
   1223	u32			num_entries;
   1224	u32			size;
   1225	u32			hook_entry[NF_INET_NUMHOOKS];
   1226	u32			underflow[NF_INET_NUMHOOKS];
   1227	u32			num_counters;
   1228	compat_uptr_t		counters;	/* struct xt_counters * */
   1229	struct compat_ip6t_entry entries[];
   1230};
   1231
   1232static int
   1233compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
   1234			  unsigned int *size, struct xt_counters *counters,
   1235			  unsigned int i)
   1236{
   1237	struct xt_entry_target *t;
   1238	struct compat_ip6t_entry __user *ce;
   1239	u_int16_t target_offset, next_offset;
   1240	compat_uint_t origsize;
   1241	const struct xt_entry_match *ematch;
   1242	int ret = 0;
   1243
   1244	origsize = *size;
   1245	ce = *dstptr;
   1246	if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 ||
   1247	    copy_to_user(&ce->counters, &counters[i],
   1248	    sizeof(counters[i])) != 0)
   1249		return -EFAULT;
   1250
   1251	*dstptr += sizeof(struct compat_ip6t_entry);
   1252	*size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
   1253
   1254	xt_ematch_foreach(ematch, e) {
   1255		ret = xt_compat_match_to_user(ematch, dstptr, size);
   1256		if (ret != 0)
   1257			return ret;
   1258	}
   1259	target_offset = e->target_offset - (origsize - *size);
   1260	t = ip6t_get_target(e);
   1261	ret = xt_compat_target_to_user(t, dstptr, size);
   1262	if (ret)
   1263		return ret;
   1264	next_offset = e->next_offset - (origsize - *size);
   1265	if (put_user(target_offset, &ce->target_offset) != 0 ||
   1266	    put_user(next_offset, &ce->next_offset) != 0)
   1267		return -EFAULT;
   1268	return 0;
   1269}
   1270
   1271static int
   1272compat_find_calc_match(struct xt_entry_match *m,
   1273		       const struct ip6t_ip6 *ipv6,
   1274		       int *size)
   1275{
   1276	struct xt_match *match;
   1277
   1278	match = xt_request_find_match(NFPROTO_IPV6, m->u.user.name,
   1279				      m->u.user.revision);
   1280	if (IS_ERR(match))
   1281		return PTR_ERR(match);
   1282
   1283	m->u.kernel.match = match;
   1284	*size += xt_compat_match_offset(match);
   1285	return 0;
   1286}
   1287
   1288static void compat_release_entry(struct compat_ip6t_entry *e)
   1289{
   1290	struct xt_entry_target *t;
   1291	struct xt_entry_match *ematch;
   1292
   1293	/* Cleanup all matches */
   1294	xt_ematch_foreach(ematch, e)
   1295		module_put(ematch->u.kernel.match->me);
   1296	t = compat_ip6t_get_target(e);
   1297	module_put(t->u.kernel.target->me);
   1298}
   1299
   1300static int
   1301check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
   1302				  struct xt_table_info *newinfo,
   1303				  unsigned int *size,
   1304				  const unsigned char *base,
   1305				  const unsigned char *limit)
   1306{
   1307	struct xt_entry_match *ematch;
   1308	struct xt_entry_target *t;
   1309	struct xt_target *target;
   1310	unsigned int entry_offset;
   1311	unsigned int j;
   1312	int ret, off;
   1313
   1314	if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
   1315	    (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit ||
   1316	    (unsigned char *)e + e->next_offset > limit)
   1317		return -EINVAL;
   1318
   1319	if (e->next_offset < sizeof(struct compat_ip6t_entry) +
   1320			     sizeof(struct compat_xt_entry_target))
   1321		return -EINVAL;
   1322
   1323	if (!ip6_checkentry(&e->ipv6))
   1324		return -EINVAL;
   1325
   1326	ret = xt_compat_check_entry_offsets(e, e->elems,
   1327					    e->target_offset, e->next_offset);
   1328	if (ret)
   1329		return ret;
   1330
   1331	off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
   1332	entry_offset = (void *)e - (void *)base;
   1333	j = 0;
   1334	xt_ematch_foreach(ematch, e) {
   1335		ret = compat_find_calc_match(ematch, &e->ipv6, &off);
   1336		if (ret != 0)
   1337			goto release_matches;
   1338		++j;
   1339	}
   1340
   1341	t = compat_ip6t_get_target(e);
   1342	target = xt_request_find_target(NFPROTO_IPV6, t->u.user.name,
   1343					t->u.user.revision);
   1344	if (IS_ERR(target)) {
   1345		ret = PTR_ERR(target);
   1346		goto release_matches;
   1347	}
   1348	t->u.kernel.target = target;
   1349
   1350	off += xt_compat_target_offset(target);
   1351	*size += off;
   1352	ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
   1353	if (ret)
   1354		goto out;
   1355
   1356	return 0;
   1357
   1358out:
   1359	module_put(t->u.kernel.target->me);
   1360release_matches:
   1361	xt_ematch_foreach(ematch, e) {
   1362		if (j-- == 0)
   1363			break;
   1364		module_put(ematch->u.kernel.match->me);
   1365	}
   1366	return ret;
   1367}
   1368
   1369static void
   1370compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
   1371			    unsigned int *size,
   1372			    struct xt_table_info *newinfo, unsigned char *base)
   1373{
   1374	struct xt_entry_target *t;
   1375	struct ip6t_entry *de;
   1376	unsigned int origsize;
   1377	int h;
   1378	struct xt_entry_match *ematch;
   1379
   1380	origsize = *size;
   1381	de = *dstptr;
   1382	memcpy(de, e, sizeof(struct ip6t_entry));
   1383	memcpy(&de->counters, &e->counters, sizeof(e->counters));
   1384
   1385	*dstptr += sizeof(struct ip6t_entry);
   1386	*size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
   1387
   1388	xt_ematch_foreach(ematch, e)
   1389		xt_compat_match_from_user(ematch, dstptr, size);
   1390
   1391	de->target_offset = e->target_offset - (origsize - *size);
   1392	t = compat_ip6t_get_target(e);
   1393	xt_compat_target_from_user(t, dstptr, size);
   1394
   1395	de->next_offset = e->next_offset - (origsize - *size);
   1396	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
   1397		if ((unsigned char *)de - base < newinfo->hook_entry[h])
   1398			newinfo->hook_entry[h] -= origsize - *size;
   1399		if ((unsigned char *)de - base < newinfo->underflow[h])
   1400			newinfo->underflow[h] -= origsize - *size;
   1401	}
   1402}
   1403
   1404static int
   1405translate_compat_table(struct net *net,
   1406		       struct xt_table_info **pinfo,
   1407		       void **pentry0,
   1408		       const struct compat_ip6t_replace *compatr)
   1409{
   1410	unsigned int i, j;
   1411	struct xt_table_info *newinfo, *info;
   1412	void *pos, *entry0, *entry1;
   1413	struct compat_ip6t_entry *iter0;
   1414	struct ip6t_replace repl;
   1415	unsigned int size;
   1416	int ret;
   1417
   1418	info = *pinfo;
   1419	entry0 = *pentry0;
   1420	size = compatr->size;
   1421	info->number = compatr->num_entries;
   1422
   1423	j = 0;
   1424	xt_compat_lock(AF_INET6);
   1425	ret = xt_compat_init_offsets(AF_INET6, compatr->num_entries);
   1426	if (ret)
   1427		goto out_unlock;
   1428	/* Walk through entries, checking offsets. */
   1429	xt_entry_foreach(iter0, entry0, compatr->size) {
   1430		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
   1431							entry0,
   1432							entry0 + compatr->size);
   1433		if (ret != 0)
   1434			goto out_unlock;
   1435		++j;
   1436	}
   1437
   1438	ret = -EINVAL;
   1439	if (j != compatr->num_entries)
   1440		goto out_unlock;
   1441
   1442	ret = -ENOMEM;
   1443	newinfo = xt_alloc_table_info(size);
   1444	if (!newinfo)
   1445		goto out_unlock;
   1446
   1447	memset(newinfo->entries, 0, size);
   1448
   1449	newinfo->number = compatr->num_entries;
   1450	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
   1451		newinfo->hook_entry[i] = compatr->hook_entry[i];
   1452		newinfo->underflow[i] = compatr->underflow[i];
   1453	}
   1454	entry1 = newinfo->entries;
   1455	pos = entry1;
   1456	size = compatr->size;
   1457	xt_entry_foreach(iter0, entry0, compatr->size)
   1458		compat_copy_entry_from_user(iter0, &pos, &size,
   1459					    newinfo, entry1);
   1460
   1461	/* all module references in entry0 are now gone. */
   1462	xt_compat_flush_offsets(AF_INET6);
   1463	xt_compat_unlock(AF_INET6);
   1464
   1465	memcpy(&repl, compatr, sizeof(*compatr));
   1466
   1467	for (i = 0; i < NF_INET_NUMHOOKS; i++) {
   1468		repl.hook_entry[i] = newinfo->hook_entry[i];
   1469		repl.underflow[i] = newinfo->underflow[i];
   1470	}
   1471
   1472	repl.num_counters = 0;
   1473	repl.counters = NULL;
   1474	repl.size = newinfo->size;
   1475	ret = translate_table(net, newinfo, entry1, &repl);
   1476	if (ret)
   1477		goto free_newinfo;
   1478
   1479	*pinfo = newinfo;
   1480	*pentry0 = entry1;
   1481	xt_free_table_info(info);
   1482	return 0;
   1483
   1484free_newinfo:
   1485	xt_free_table_info(newinfo);
   1486	return ret;
   1487out_unlock:
   1488	xt_compat_flush_offsets(AF_INET6);
   1489	xt_compat_unlock(AF_INET6);
   1490	xt_entry_foreach(iter0, entry0, compatr->size) {
   1491		if (j-- == 0)
   1492			break;
   1493		compat_release_entry(iter0);
   1494	}
   1495	return ret;
   1496}
   1497
   1498static int
   1499compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
   1500{
   1501	int ret;
   1502	struct compat_ip6t_replace tmp;
   1503	struct xt_table_info *newinfo;
   1504	void *loc_cpu_entry;
   1505	struct ip6t_entry *iter;
   1506
   1507	if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
   1508		return -EFAULT;
   1509
   1510	/* overflow check */
   1511	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
   1512		return -ENOMEM;
   1513	if (tmp.num_counters == 0)
   1514		return -EINVAL;
   1515
   1516	tmp.name[sizeof(tmp.name)-1] = 0;
   1517
   1518	newinfo = xt_alloc_table_info(tmp.size);
   1519	if (!newinfo)
   1520		return -ENOMEM;
   1521
   1522	loc_cpu_entry = newinfo->entries;
   1523	if (copy_from_sockptr_offset(loc_cpu_entry, arg, sizeof(tmp),
   1524			tmp.size) != 0) {
   1525		ret = -EFAULT;
   1526		goto free_newinfo;
   1527	}
   1528
   1529	ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
   1530	if (ret != 0)
   1531		goto free_newinfo;
   1532
   1533	ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
   1534			   tmp.num_counters, compat_ptr(tmp.counters));
   1535	if (ret)
   1536		goto free_newinfo_untrans;
   1537	return 0;
   1538
   1539 free_newinfo_untrans:
   1540	xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
   1541		cleanup_entry(iter, net);
   1542 free_newinfo:
   1543	xt_free_table_info(newinfo);
   1544	return ret;
   1545}
   1546
   1547struct compat_ip6t_get_entries {
   1548	char name[XT_TABLE_MAXNAMELEN];
   1549	compat_uint_t size;
   1550	struct compat_ip6t_entry entrytable[];
   1551};
   1552
   1553static int
   1554compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
   1555			    void __user *userptr)
   1556{
   1557	struct xt_counters *counters;
   1558	const struct xt_table_info *private = table->private;
   1559	void __user *pos;
   1560	unsigned int size;
   1561	int ret = 0;
   1562	unsigned int i = 0;
   1563	struct ip6t_entry *iter;
   1564
   1565	counters = alloc_counters(table);
   1566	if (IS_ERR(counters))
   1567		return PTR_ERR(counters);
   1568
   1569	pos = userptr;
   1570	size = total_size;
   1571	xt_entry_foreach(iter, private->entries, total_size) {
   1572		ret = compat_copy_entry_to_user(iter, &pos,
   1573						&size, counters, i++);
   1574		if (ret != 0)
   1575			break;
   1576	}
   1577
   1578	vfree(counters);
   1579	return ret;
   1580}
   1581
   1582static int
   1583compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
   1584		   int *len)
   1585{
   1586	int ret;
   1587	struct compat_ip6t_get_entries get;
   1588	struct xt_table *t;
   1589
   1590	if (*len < sizeof(get))
   1591		return -EINVAL;
   1592
   1593	if (copy_from_user(&get, uptr, sizeof(get)) != 0)
   1594		return -EFAULT;
   1595
   1596	if (*len != sizeof(struct compat_ip6t_get_entries) + get.size)
   1597		return -EINVAL;
   1598
   1599	get.name[sizeof(get.name) - 1] = '\0';
   1600
   1601	xt_compat_lock(AF_INET6);
   1602	t = xt_find_table_lock(net, AF_INET6, get.name);
   1603	if (!IS_ERR(t)) {
   1604		const struct xt_table_info *private = t->private;
   1605		struct xt_table_info info;
   1606		ret = compat_table_info(private, &info);
   1607		if (!ret && get.size == info.size)
   1608			ret = compat_copy_entries_to_user(private->size,
   1609							  t, uptr->entrytable);
   1610		else if (!ret)
   1611			ret = -EAGAIN;
   1612
   1613		xt_compat_flush_offsets(AF_INET6);
   1614		module_put(t->me);
   1615		xt_table_unlock(t);
   1616	} else
   1617		ret = PTR_ERR(t);
   1618
   1619	xt_compat_unlock(AF_INET6);
   1620	return ret;
   1621}
   1622#endif
   1623
   1624static int
   1625do_ip6t_set_ctl(struct sock *sk, int cmd, sockptr_t arg, unsigned int len)
   1626{
   1627	int ret;
   1628
   1629	if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
   1630		return -EPERM;
   1631
   1632	switch (cmd) {
   1633	case IP6T_SO_SET_REPLACE:
   1634#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
   1635		if (in_compat_syscall())
   1636			ret = compat_do_replace(sock_net(sk), arg, len);
   1637		else
   1638#endif
   1639			ret = do_replace(sock_net(sk), arg, len);
   1640		break;
   1641
   1642	case IP6T_SO_SET_ADD_COUNTERS:
   1643		ret = do_add_counters(sock_net(sk), arg, len);
   1644		break;
   1645
   1646	default:
   1647		ret = -EINVAL;
   1648	}
   1649
   1650	return ret;
   1651}
   1652
   1653static int
   1654do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
   1655{
   1656	int ret;
   1657
   1658	if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
   1659		return -EPERM;
   1660
   1661	switch (cmd) {
   1662	case IP6T_SO_GET_INFO:
   1663		ret = get_info(sock_net(sk), user, len);
   1664		break;
   1665
   1666	case IP6T_SO_GET_ENTRIES:
   1667#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
   1668		if (in_compat_syscall())
   1669			ret = compat_get_entries(sock_net(sk), user, len);
   1670		else
   1671#endif
   1672			ret = get_entries(sock_net(sk), user, len);
   1673		break;
   1674
   1675	case IP6T_SO_GET_REVISION_MATCH:
   1676	case IP6T_SO_GET_REVISION_TARGET: {
   1677		struct xt_get_revision rev;
   1678		int target;
   1679
   1680		if (*len != sizeof(rev)) {
   1681			ret = -EINVAL;
   1682			break;
   1683		}
   1684		if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
   1685			ret = -EFAULT;
   1686			break;
   1687		}
   1688		rev.name[sizeof(rev.name)-1] = 0;
   1689
   1690		if (cmd == IP6T_SO_GET_REVISION_TARGET)
   1691			target = 1;
   1692		else
   1693			target = 0;
   1694
   1695		try_then_request_module(xt_find_revision(AF_INET6, rev.name,
   1696							 rev.revision,
   1697							 target, &ret),
   1698					"ip6t_%s", rev.name);
   1699		break;
   1700	}
   1701
   1702	default:
   1703		ret = -EINVAL;
   1704	}
   1705
   1706	return ret;
   1707}
   1708
   1709static void __ip6t_unregister_table(struct net *net, struct xt_table *table)
   1710{
   1711	struct xt_table_info *private;
   1712	void *loc_cpu_entry;
   1713	struct module *table_owner = table->me;
   1714	struct ip6t_entry *iter;
   1715
   1716	private = xt_unregister_table(table);
   1717
   1718	/* Decrease module usage counts and free resources */
   1719	loc_cpu_entry = private->entries;
   1720	xt_entry_foreach(iter, loc_cpu_entry, private->size)
   1721		cleanup_entry(iter, net);
   1722	if (private->number > private->initial_entries)
   1723		module_put(table_owner);
   1724	xt_free_table_info(private);
   1725}
   1726
   1727int ip6t_register_table(struct net *net, const struct xt_table *table,
   1728			const struct ip6t_replace *repl,
   1729			const struct nf_hook_ops *template_ops)
   1730{
   1731	struct nf_hook_ops *ops;
   1732	unsigned int num_ops;
   1733	int ret, i;
   1734	struct xt_table_info *newinfo;
   1735	struct xt_table_info bootstrap = {0};
   1736	void *loc_cpu_entry;
   1737	struct xt_table *new_table;
   1738
   1739	newinfo = xt_alloc_table_info(repl->size);
   1740	if (!newinfo)
   1741		return -ENOMEM;
   1742
   1743	loc_cpu_entry = newinfo->entries;
   1744	memcpy(loc_cpu_entry, repl->entries, repl->size);
   1745
   1746	ret = translate_table(net, newinfo, loc_cpu_entry, repl);
   1747	if (ret != 0) {
   1748		xt_free_table_info(newinfo);
   1749		return ret;
   1750	}
   1751
   1752	new_table = xt_register_table(net, table, &bootstrap, newinfo);
   1753	if (IS_ERR(new_table)) {
   1754		xt_free_table_info(newinfo);
   1755		return PTR_ERR(new_table);
   1756	}
   1757
   1758	if (!template_ops)
   1759		return 0;
   1760
   1761	num_ops = hweight32(table->valid_hooks);
   1762	if (num_ops == 0) {
   1763		ret = -EINVAL;
   1764		goto out_free;
   1765	}
   1766
   1767	ops = kmemdup(template_ops, sizeof(*ops) * num_ops, GFP_KERNEL);
   1768	if (!ops) {
   1769		ret = -ENOMEM;
   1770		goto out_free;
   1771	}
   1772
   1773	for (i = 0; i < num_ops; i++)
   1774		ops[i].priv = new_table;
   1775
   1776	new_table->ops = ops;
   1777
   1778	ret = nf_register_net_hooks(net, ops, num_ops);
   1779	if (ret != 0)
   1780		goto out_free;
   1781
   1782	return ret;
   1783
   1784out_free:
   1785	__ip6t_unregister_table(net, new_table);
   1786	return ret;
   1787}
   1788
   1789void ip6t_unregister_table_pre_exit(struct net *net, const char *name)
   1790{
   1791	struct xt_table *table = xt_find_table(net, NFPROTO_IPV6, name);
   1792
   1793	if (table)
   1794		nf_unregister_net_hooks(net, table->ops, hweight32(table->valid_hooks));
   1795}
   1796
   1797void ip6t_unregister_table_exit(struct net *net, const char *name)
   1798{
   1799	struct xt_table *table = xt_find_table(net, NFPROTO_IPV6, name);
   1800
   1801	if (table)
   1802		__ip6t_unregister_table(net, table);
   1803}
   1804
   1805/* Returns 1 if the type and code is matched by the range, 0 otherwise */
   1806static inline bool
   1807icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
   1808		     u_int8_t type, u_int8_t code,
   1809		     bool invert)
   1810{
   1811	return (type == test_type && code >= min_code && code <= max_code)
   1812		^ invert;
   1813}
   1814
   1815static bool
   1816icmp6_match(const struct sk_buff *skb, struct xt_action_param *par)
   1817{
   1818	const struct icmp6hdr *ic;
   1819	struct icmp6hdr _icmph;
   1820	const struct ip6t_icmp *icmpinfo = par->matchinfo;
   1821
   1822	/* Must not be a fragment. */
   1823	if (par->fragoff != 0)
   1824		return false;
   1825
   1826	ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
   1827	if (ic == NULL) {
   1828		/* We've been asked to examine this packet, and we
   1829		 * can't.  Hence, no choice but to drop.
   1830		 */
   1831		par->hotdrop = true;
   1832		return false;
   1833	}
   1834
   1835	return icmp6_type_code_match(icmpinfo->type,
   1836				     icmpinfo->code[0],
   1837				     icmpinfo->code[1],
   1838				     ic->icmp6_type, ic->icmp6_code,
   1839				     !!(icmpinfo->invflags&IP6T_ICMP_INV));
   1840}
   1841
   1842/* Called when user tries to insert an entry of this type. */
   1843static int icmp6_checkentry(const struct xt_mtchk_param *par)
   1844{
   1845	const struct ip6t_icmp *icmpinfo = par->matchinfo;
   1846
   1847	/* Must specify no unknown invflags */
   1848	return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0;
   1849}
   1850
   1851/* The built-in targets: standard (NULL) and error. */
   1852static struct xt_target ip6t_builtin_tg[] __read_mostly = {
   1853	{
   1854		.name             = XT_STANDARD_TARGET,
   1855		.targetsize       = sizeof(int),
   1856		.family           = NFPROTO_IPV6,
   1857#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
   1858		.compatsize       = sizeof(compat_int_t),
   1859		.compat_from_user = compat_standard_from_user,
   1860		.compat_to_user   = compat_standard_to_user,
   1861#endif
   1862	},
   1863	{
   1864		.name             = XT_ERROR_TARGET,
   1865		.target           = ip6t_error,
   1866		.targetsize       = XT_FUNCTION_MAXNAMELEN,
   1867		.family           = NFPROTO_IPV6,
   1868	},
   1869};
   1870
   1871static struct nf_sockopt_ops ip6t_sockopts = {
   1872	.pf		= PF_INET6,
   1873	.set_optmin	= IP6T_BASE_CTL,
   1874	.set_optmax	= IP6T_SO_SET_MAX+1,
   1875	.set		= do_ip6t_set_ctl,
   1876	.get_optmin	= IP6T_BASE_CTL,
   1877	.get_optmax	= IP6T_SO_GET_MAX+1,
   1878	.get		= do_ip6t_get_ctl,
   1879	.owner		= THIS_MODULE,
   1880};
   1881
   1882static struct xt_match ip6t_builtin_mt[] __read_mostly = {
   1883	{
   1884		.name       = "icmp6",
   1885		.match      = icmp6_match,
   1886		.matchsize  = sizeof(struct ip6t_icmp),
   1887		.checkentry = icmp6_checkentry,
   1888		.proto      = IPPROTO_ICMPV6,
   1889		.family     = NFPROTO_IPV6,
   1890		.me	    = THIS_MODULE,
   1891	},
   1892};
   1893
   1894static int __net_init ip6_tables_net_init(struct net *net)
   1895{
   1896	return xt_proto_init(net, NFPROTO_IPV6);
   1897}
   1898
   1899static void __net_exit ip6_tables_net_exit(struct net *net)
   1900{
   1901	xt_proto_fini(net, NFPROTO_IPV6);
   1902}
   1903
   1904static struct pernet_operations ip6_tables_net_ops = {
   1905	.init = ip6_tables_net_init,
   1906	.exit = ip6_tables_net_exit,
   1907};
   1908
   1909static int __init ip6_tables_init(void)
   1910{
   1911	int ret;
   1912
   1913	ret = register_pernet_subsys(&ip6_tables_net_ops);
   1914	if (ret < 0)
   1915		goto err1;
   1916
   1917	/* No one else will be downing sem now, so we won't sleep */
   1918	ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
   1919	if (ret < 0)
   1920		goto err2;
   1921	ret = xt_register_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
   1922	if (ret < 0)
   1923		goto err4;
   1924
   1925	/* Register setsockopt */
   1926	ret = nf_register_sockopt(&ip6t_sockopts);
   1927	if (ret < 0)
   1928		goto err5;
   1929
   1930	return 0;
   1931
   1932err5:
   1933	xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
   1934err4:
   1935	xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
   1936err2:
   1937	unregister_pernet_subsys(&ip6_tables_net_ops);
   1938err1:
   1939	return ret;
   1940}
   1941
   1942static void __exit ip6_tables_fini(void)
   1943{
   1944	nf_unregister_sockopt(&ip6t_sockopts);
   1945
   1946	xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
   1947	xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
   1948	unregister_pernet_subsys(&ip6_tables_net_ops);
   1949}
   1950
   1951EXPORT_SYMBOL(ip6t_register_table);
   1952EXPORT_SYMBOL(ip6t_unregister_table_pre_exit);
   1953EXPORT_SYMBOL(ip6t_unregister_table_exit);
   1954EXPORT_SYMBOL(ip6t_do_table);
   1955
   1956module_init(ip6_tables_init);
   1957module_exit(ip6_tables_fini);