OSDN Git Service

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