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