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