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