1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Packet matching code for ARP packets.
4 *
5 * Based heavily, if not almost entirely, upon ip_tables.c framework.
6 *
7 * Some ARP specific bits are:
8 *
9 * Copyright (C) 2002 David S. Miller (davem@redhat.com)
10 * Copyright (C) 2006-2009 Patrick McHardy <kaber@trash.net>
11 *
12 */
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 #include <linux/kernel.h>
15 #include <linux/skbuff.h>
16 #include <linux/netdevice.h>
17 #include <linux/capability.h>
18 #include <linux/if_arp.h>
19 #include <linux/kmod.h>
20 #include <linux/vmalloc.h>
21 #include <linux/proc_fs.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/mutex.h>
25 #include <linux/err.h>
26 #include <net/sock.h>
27 #include <linux/uaccess.h>
28
29 #include <linux/netfilter/x_tables.h>
30 #include <linux/netfilter_arp/arp_tables.h>
31 #include "../../netfilter/xt_repldata.h"
32
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
35 MODULE_DESCRIPTION("arptables core");
36
arpt_alloc_initial_table(const struct xt_table * info)37 void *arpt_alloc_initial_table(const struct xt_table *info)
38 {
39 return xt_alloc_initial_table(arpt, ARPT);
40 }
41 EXPORT_SYMBOL_GPL(arpt_alloc_initial_table);
42
arp_devaddr_compare(const struct arpt_devaddr_info * ap,const char * hdr_addr,int len)43 static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
44 const char *hdr_addr, int len)
45 {
46 int i, ret;
47
48 if (len > ARPT_DEV_ADDR_LEN_MAX)
49 len = ARPT_DEV_ADDR_LEN_MAX;
50
51 ret = 0;
52 for (i = 0; i < len; i++)
53 ret |= (hdr_addr[i] ^ ap->addr[i]) & ap->mask[i];
54
55 return ret != 0;
56 }
57
58 /*
59 * Unfortunately, _b and _mask are not aligned to an int (or long int)
60 * Some arches dont care, unrolling the loop is a win on them.
61 * For other arches, we only have a 16bit alignement.
62 */
ifname_compare(const char * _a,const char * _b,const char * _mask)63 static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask)
64 {
65 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
66 unsigned long ret = ifname_compare_aligned(_a, _b, _mask);
67 #else
68 unsigned long ret = 0;
69 const u16 *a = (const u16 *)_a;
70 const u16 *b = (const u16 *)_b;
71 const u16 *mask = (const u16 *)_mask;
72 int i;
73
74 for (i = 0; i < IFNAMSIZ/sizeof(u16); i++)
75 ret |= (a[i] ^ b[i]) & mask[i];
76 #endif
77 return ret;
78 }
79
80 /* Returns whether packet matches rule or not. */
arp_packet_match(const struct arphdr * arphdr,struct net_device * dev,const char * indev,const char * outdev,const struct arpt_arp * arpinfo)81 static inline int arp_packet_match(const struct arphdr *arphdr,
82 struct net_device *dev,
83 const char *indev,
84 const char *outdev,
85 const struct arpt_arp *arpinfo)
86 {
87 const char *arpptr = (char *)(arphdr + 1);
88 const char *src_devaddr, *tgt_devaddr;
89 __be32 src_ipaddr, tgt_ipaddr;
90 long ret;
91
92 if (NF_INVF(arpinfo, ARPT_INV_ARPOP,
93 (arphdr->ar_op & arpinfo->arpop_mask) != arpinfo->arpop))
94 return 0;
95
96 if (NF_INVF(arpinfo, ARPT_INV_ARPHRD,
97 (arphdr->ar_hrd & arpinfo->arhrd_mask) != arpinfo->arhrd))
98 return 0;
99
100 if (NF_INVF(arpinfo, ARPT_INV_ARPPRO,
101 (arphdr->ar_pro & arpinfo->arpro_mask) != arpinfo->arpro))
102 return 0;
103
104 if (NF_INVF(arpinfo, ARPT_INV_ARPHLN,
105 (arphdr->ar_hln & arpinfo->arhln_mask) != arpinfo->arhln))
106 return 0;
107
108 src_devaddr = arpptr;
109 arpptr += dev->addr_len;
110 memcpy(&src_ipaddr, arpptr, sizeof(u32));
111 arpptr += sizeof(u32);
112
113 if (IS_ENABLED(CONFIG_FIREWIRE_NET) && dev->type == ARPHRD_IEEE1394) {
114 if (unlikely(memchr_inv(arpinfo->tgt_devaddr.mask, 0,
115 sizeof(arpinfo->tgt_devaddr.mask))))
116 return 0;
117
118 tgt_devaddr = NULL;
119 } else {
120 tgt_devaddr = arpptr;
121 arpptr += dev->addr_len;
122 }
123 memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
124
125 if (NF_INVF(arpinfo, ARPT_INV_SRCDEVADDR,
126 arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr,
127 dev->addr_len)))
128 return 0;
129
130 if (tgt_devaddr &&
131 NF_INVF(arpinfo, ARPT_INV_TGTDEVADDR,
132 arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr,
133 dev->addr_len)))
134 return 0;
135
136 if (NF_INVF(arpinfo, ARPT_INV_SRCIP,
137 (src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr) ||
138 NF_INVF(arpinfo, ARPT_INV_TGTIP,
139 (tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr))
140 return 0;
141
142 /* Look for ifname matches. */
143 ret = ifname_compare(indev, arpinfo->iniface, arpinfo->iniface_mask);
144
145 if (NF_INVF(arpinfo, ARPT_INV_VIA_IN, ret != 0))
146 return 0;
147
148 ret = ifname_compare(outdev, arpinfo->outiface, arpinfo->outiface_mask);
149
150 if (NF_INVF(arpinfo, ARPT_INV_VIA_OUT, ret != 0))
151 return 0;
152
153 return 1;
154 }
155
arp_checkentry(const struct arpt_arp * arp)156 static inline int arp_checkentry(const struct arpt_arp *arp)
157 {
158 if (arp->flags & ~ARPT_F_MASK)
159 return 0;
160 if (arp->invflags & ~ARPT_INV_MASK)
161 return 0;
162
163 return 1;
164 }
165
166 static unsigned int
arpt_error(struct sk_buff * skb,const struct xt_action_param * par)167 arpt_error(struct sk_buff *skb, const struct xt_action_param *par)
168 {
169 net_err_ratelimited("arp_tables: error: '%s'\n",
170 (const char *)par->targinfo);
171
172 return NF_DROP;
173 }
174
175 static inline const struct xt_entry_target *
arpt_get_target_c(const struct arpt_entry * e)176 arpt_get_target_c(const struct arpt_entry *e)
177 {
178 return arpt_get_target((struct arpt_entry *)e);
179 }
180
181 static inline struct arpt_entry *
get_entry(const void * base,unsigned int offset)182 get_entry(const void *base, unsigned int offset)
183 {
184 return (struct arpt_entry *)(base + offset);
185 }
186
187 static inline
arpt_next_entry(const struct arpt_entry * entry)188 struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry)
189 {
190 return (void *)entry + entry->next_offset;
191 }
192
arpt_do_table(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)193 unsigned int arpt_do_table(void *priv,
194 struct sk_buff *skb,
195 const struct nf_hook_state *state)
196 {
197 const struct xt_table *table = priv;
198 unsigned int hook = state->hook;
199 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
200 unsigned int verdict = NF_DROP;
201 const struct arphdr *arp;
202 struct arpt_entry *e, **jumpstack;
203 const char *indev, *outdev;
204 const void *table_base;
205 unsigned int cpu, stackidx = 0;
206 const struct xt_table_info *private;
207 struct xt_action_param acpar;
208 unsigned int addend;
209
210 if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
211 return NF_DROP;
212
213 indev = state->in ? state->in->name : nulldevname;
214 outdev = state->out ? state->out->name : nulldevname;
215
216 local_bh_disable();
217 addend = xt_write_recseq_begin();
218 private = READ_ONCE(table->private); /* Address dependency. */
219 cpu = smp_processor_id();
220 table_base = private->entries;
221 jumpstack = (struct arpt_entry **)private->jumpstack[cpu];
222
223 /* No TEE support for arptables, so no need to switch to alternate
224 * stack. All targets that reenter must return absolute verdicts.
225 */
226 e = get_entry(table_base, private->hook_entry[hook]);
227
228 acpar.state = state;
229 acpar.hotdrop = false;
230
231 arp = arp_hdr(skb);
232 do {
233 const struct xt_entry_target *t;
234 struct xt_counters *counter;
235
236 if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
237 e = arpt_next_entry(e);
238 continue;
239 }
240
241 counter = xt_get_this_cpu_counter(&e->counters);
242 ADD_COUNTER(*counter, arp_hdr_len(skb->dev), 1);
243
244 t = arpt_get_target_c(e);
245
246 /* Standard target? */
247 if (!t->u.kernel.target->target) {
248 int v;
249
250 v = ((struct xt_standard_target *)t)->verdict;
251 if (v < 0) {
252 /* Pop from stack? */
253 if (v != XT_RETURN) {
254 verdict = (unsigned int)(-v) - 1;
255 break;
256 }
257 if (stackidx == 0) {
258 e = get_entry(table_base,
259 private->underflow[hook]);
260 } else {
261 e = jumpstack[--stackidx];
262 e = arpt_next_entry(e);
263 }
264 continue;
265 }
266 if (table_base + v
267 != arpt_next_entry(e)) {
268 if (unlikely(stackidx >= private->stacksize)) {
269 verdict = NF_DROP;
270 break;
271 }
272 jumpstack[stackidx++] = e;
273 }
274
275 e = get_entry(table_base, v);
276 continue;
277 }
278
279 acpar.target = t->u.kernel.target;
280 acpar.targinfo = t->data;
281 verdict = t->u.kernel.target->target(skb, &acpar);
282
283 if (verdict == XT_CONTINUE) {
284 /* Target might have changed stuff. */
285 arp = arp_hdr(skb);
286 e = arpt_next_entry(e);
287 } else {
288 /* Verdict */
289 break;
290 }
291 } while (!acpar.hotdrop);
292 xt_write_recseq_end(addend);
293 local_bh_enable();
294
295 if (acpar.hotdrop)
296 return NF_DROP;
297 else
298 return verdict;
299 }
300
301 /* All zeroes == unconditional rule. */
unconditional(const struct arpt_entry * e)302 static inline bool unconditional(const struct arpt_entry *e)
303 {
304 static const struct arpt_arp uncond;
305
306 return e->target_offset == sizeof(struct arpt_entry) &&
307 memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
308 }
309
310 /* Figures out from what hook each rule can be called: returns 0 if
311 * there are loops. Puts hook bitmask in comefrom.
312 */
mark_source_chains(const struct xt_table_info * newinfo,unsigned int valid_hooks,void * entry0,unsigned int * offsets)313 static int mark_source_chains(const struct xt_table_info *newinfo,
314 unsigned int valid_hooks, void *entry0,
315 unsigned int *offsets)
316 {
317 unsigned int hook;
318
319 /* No recursion; use packet counter to save back ptrs (reset
320 * to 0 as we leave), and comefrom to save source hook bitmask.
321 */
322 for (hook = 0; hook < NF_ARP_NUMHOOKS; hook++) {
323 unsigned int pos = newinfo->hook_entry[hook];
324 struct arpt_entry *e = entry0 + pos;
325
326 if (!(valid_hooks & (1 << hook)))
327 continue;
328
329 /* Set initial back pointer. */
330 e->counters.pcnt = pos;
331
332 for (;;) {
333 const struct xt_standard_target *t
334 = (void *)arpt_get_target_c(e);
335 int visited = e->comefrom & (1 << hook);
336
337 if (e->comefrom & (1 << NF_ARP_NUMHOOKS))
338 return 0;
339
340 e->comefrom
341 |= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
342
343 /* Unconditional return/END. */
344 if ((unconditional(e) &&
345 (strcmp(t->target.u.user.name,
346 XT_STANDARD_TARGET) == 0) &&
347 t->verdict < 0) || visited) {
348 unsigned int oldpos, size;
349
350 /* Return: backtrack through the last
351 * big jump.
352 */
353 do {
354 e->comefrom ^= (1<<NF_ARP_NUMHOOKS);
355 oldpos = pos;
356 pos = e->counters.pcnt;
357 e->counters.pcnt = 0;
358
359 /* We're at the start. */
360 if (pos == oldpos)
361 goto next;
362
363 e = entry0 + pos;
364 } while (oldpos == pos + e->next_offset);
365
366 /* Move along one */
367 size = e->next_offset;
368 e = entry0 + pos + size;
369 if (pos + size >= newinfo->size)
370 return 0;
371 e->counters.pcnt = pos;
372 pos += size;
373 } else {
374 int newpos = t->verdict;
375
376 if (strcmp(t->target.u.user.name,
377 XT_STANDARD_TARGET) == 0 &&
378 newpos >= 0) {
379 /* This a jump; chase it. */
380 if (!xt_find_jump_offset(offsets, newpos,
381 newinfo->number))
382 return 0;
383 } else {
384 /* ... this is a fallthru */
385 newpos = pos + e->next_offset;
386 if (newpos >= newinfo->size)
387 return 0;
388 }
389 e = entry0 + newpos;
390 e->counters.pcnt = pos;
391 pos = newpos;
392 }
393 }
394 next: ;
395 }
396 return 1;
397 }
398
check_target(struct arpt_entry * e,struct net * net,const char * name)399 static int check_target(struct arpt_entry *e, struct net *net, const char *name)
400 {
401 struct xt_entry_target *t = arpt_get_target(e);
402 struct xt_tgchk_param par = {
403 .net = net,
404 .table = name,
405 .entryinfo = e,
406 .target = t->u.kernel.target,
407 .targinfo = t->data,
408 .hook_mask = e->comefrom,
409 .family = NFPROTO_ARP,
410 };
411
412 return xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
413 }
414
415 static int
find_check_entry(struct arpt_entry * e,struct net * net,const char * name,unsigned int size,struct xt_percpu_counter_alloc_state * alloc_state)416 find_check_entry(struct arpt_entry *e, struct net *net, const char *name,
417 unsigned int size,
418 struct xt_percpu_counter_alloc_state *alloc_state)
419 {
420 struct xt_entry_target *t;
421 struct xt_target *target;
422 int ret;
423
424 if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
425 return -ENOMEM;
426
427 t = arpt_get_target(e);
428 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name,
429 t->u.user.revision);
430 if (IS_ERR(target)) {
431 ret = PTR_ERR(target);
432 goto out;
433 }
434 t->u.kernel.target = target;
435
436 ret = check_target(e, net, name);
437 if (ret)
438 goto err;
439 return 0;
440 err:
441 module_put(t->u.kernel.target->me);
442 out:
443 xt_percpu_counter_free(&e->counters);
444
445 return ret;
446 }
447
check_underflow(const struct arpt_entry * e)448 static bool check_underflow(const struct arpt_entry *e)
449 {
450 const struct xt_entry_target *t;
451 unsigned int verdict;
452
453 if (!unconditional(e))
454 return false;
455 t = arpt_get_target_c(e);
456 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
457 return false;
458 verdict = ((struct xt_standard_target *)t)->verdict;
459 verdict = -verdict - 1;
460 return verdict == NF_DROP || verdict == NF_ACCEPT;
461 }
462
check_entry_size_and_hooks(struct arpt_entry * e,struct xt_table_info * newinfo,const unsigned char * base,const unsigned char * limit,const unsigned int * hook_entries,const unsigned int * underflows,unsigned int valid_hooks)463 static inline int check_entry_size_and_hooks(struct arpt_entry *e,
464 struct xt_table_info *newinfo,
465 const unsigned char *base,
466 const unsigned char *limit,
467 const unsigned int *hook_entries,
468 const unsigned int *underflows,
469 unsigned int valid_hooks)
470 {
471 unsigned int h;
472 int err;
473
474 if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 ||
475 (unsigned char *)e + sizeof(struct arpt_entry) >= limit ||
476 (unsigned char *)e + e->next_offset > limit)
477 return -EINVAL;
478
479 if (e->next_offset
480 < sizeof(struct arpt_entry) + sizeof(struct xt_entry_target))
481 return -EINVAL;
482
483 if (!arp_checkentry(&e->arp))
484 return -EINVAL;
485
486 err = xt_check_entry_offsets(e, e->elems, e->target_offset,
487 e->next_offset);
488 if (err)
489 return err;
490
491 /* Check hooks & underflows */
492 for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
493 if (!(valid_hooks & (1 << h)))
494 continue;
495 if ((unsigned char *)e - base == hook_entries[h])
496 newinfo->hook_entry[h] = hook_entries[h];
497 if ((unsigned char *)e - base == underflows[h]) {
498 if (!check_underflow(e))
499 return -EINVAL;
500
501 newinfo->underflow[h] = underflows[h];
502 }
503 }
504
505 /* Clear counters and comefrom */
506 e->counters = ((struct xt_counters) { 0, 0 });
507 e->comefrom = 0;
508 return 0;
509 }
510
cleanup_entry(struct arpt_entry * e,struct net * net)511 static void cleanup_entry(struct arpt_entry *e, struct net *net)
512 {
513 struct xt_tgdtor_param par;
514 struct xt_entry_target *t;
515
516 t = arpt_get_target(e);
517 par.net = net;
518 par.target = t->u.kernel.target;
519 par.targinfo = t->data;
520 par.family = NFPROTO_ARP;
521 if (par.target->destroy != NULL)
522 par.target->destroy(&par);
523 module_put(par.target->me);
524 xt_percpu_counter_free(&e->counters);
525 }
526
527 /* Checks and translates the user-supplied table segment (held in
528 * newinfo).
529 */
translate_table(struct net * net,struct xt_table_info * newinfo,void * entry0,const struct arpt_replace * repl)530 static int translate_table(struct net *net,
531 struct xt_table_info *newinfo,
532 void *entry0,
533 const struct arpt_replace *repl)
534 {
535 struct xt_percpu_counter_alloc_state alloc_state = { 0 };
536 struct arpt_entry *iter;
537 unsigned int *offsets;
538 unsigned int i;
539 int ret = 0;
540
541 newinfo->size = repl->size;
542 newinfo->number = repl->num_entries;
543
544 /* Init all hooks to impossible value. */
545 for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
546 newinfo->hook_entry[i] = 0xFFFFFFFF;
547 newinfo->underflow[i] = 0xFFFFFFFF;
548 }
549
550 offsets = xt_alloc_entry_offsets(newinfo->number);
551 if (!offsets)
552 return -ENOMEM;
553 i = 0;
554
555 /* Walk through entries, checking offsets. */
556 xt_entry_foreach(iter, entry0, newinfo->size) {
557 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
558 entry0 + repl->size,
559 repl->hook_entry,
560 repl->underflow,
561 repl->valid_hooks);
562 if (ret != 0)
563 goto out_free;
564 if (i < repl->num_entries)
565 offsets[i] = (void *)iter - entry0;
566 ++i;
567 if (strcmp(arpt_get_target(iter)->u.user.name,
568 XT_ERROR_TARGET) == 0)
569 ++newinfo->stacksize;
570 }
571
572 ret = -EINVAL;
573 if (i != repl->num_entries)
574 goto out_free;
575
576 ret = xt_check_table_hooks(newinfo, repl->valid_hooks);
577 if (ret)
578 goto out_free;
579
580 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0, offsets)) {
581 ret = -ELOOP;
582 goto out_free;
583 }
584 kvfree(offsets);
585
586 /* Finally, each sanity check must pass */
587 i = 0;
588 xt_entry_foreach(iter, entry0, newinfo->size) {
589 ret = find_check_entry(iter, net, repl->name, repl->size,
590 &alloc_state);
591 if (ret != 0)
592 break;
593 ++i;
594 }
595
596 if (ret != 0) {
597 xt_entry_foreach(iter, entry0, newinfo->size) {
598 if (i-- == 0)
599 break;
600 cleanup_entry(iter, net);
601 }
602 return ret;
603 }
604
605 return ret;
606 out_free:
607 kvfree(offsets);
608 return ret;
609 }
610
get_counters(const struct xt_table_info * t,struct xt_counters counters[])611 static void get_counters(const struct xt_table_info *t,
612 struct xt_counters counters[])
613 {
614 struct arpt_entry *iter;
615 unsigned int cpu;
616 unsigned int i;
617
618 for_each_possible_cpu(cpu) {
619 seqcount_t *s = &per_cpu(xt_recseq, cpu);
620
621 i = 0;
622 xt_entry_foreach(iter, t->entries, t->size) {
623 struct xt_counters *tmp;
624 u64 bcnt, pcnt;
625 unsigned int start;
626
627 tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
628 do {
629 start = read_seqcount_begin(s);
630 bcnt = tmp->bcnt;
631 pcnt = tmp->pcnt;
632 } while (read_seqcount_retry(s, start));
633
634 ADD_COUNTER(counters[i], bcnt, pcnt);
635 ++i;
636 cond_resched();
637 }
638 }
639 }
640
get_old_counters(const struct xt_table_info * t,struct xt_counters counters[])641 static void get_old_counters(const struct xt_table_info *t,
642 struct xt_counters counters[])
643 {
644 struct arpt_entry *iter;
645 unsigned int cpu, i;
646
647 for_each_possible_cpu(cpu) {
648 i = 0;
649 xt_entry_foreach(iter, t->entries, t->size) {
650 struct xt_counters *tmp;
651
652 tmp = xt_get_per_cpu_counter(&iter->counters, cpu);
653 ADD_COUNTER(counters[i], tmp->bcnt, tmp->pcnt);
654 ++i;
655 }
656 cond_resched();
657 }
658 }
659
alloc_counters(const struct xt_table * table)660 static struct xt_counters *alloc_counters(const struct xt_table *table)
661 {
662 unsigned int countersize;
663 struct xt_counters *counters;
664 const struct xt_table_info *private = table->private;
665
666 /* We need atomic snapshot of counters: rest doesn't change
667 * (other than comefrom, which userspace doesn't care
668 * about).
669 */
670 countersize = sizeof(struct xt_counters) * private->number;
671 counters = vzalloc(countersize);
672
673 if (counters == NULL)
674 return ERR_PTR(-ENOMEM);
675
676 get_counters(private, counters);
677
678 return counters;
679 }
680
copy_entries_to_user(unsigned int total_size,const struct xt_table * table,void __user * userptr)681 static int copy_entries_to_user(unsigned int total_size,
682 const struct xt_table *table,
683 void __user *userptr)
684 {
685 unsigned int off, num;
686 const struct arpt_entry *e;
687 struct xt_counters *counters;
688 struct xt_table_info *private = table->private;
689 int ret = 0;
690 void *loc_cpu_entry;
691
692 counters = alloc_counters(table);
693 if (IS_ERR(counters))
694 return PTR_ERR(counters);
695
696 loc_cpu_entry = private->entries;
697
698 /* FIXME: use iterator macros --RR */
699 /* ... then go back and fix counters and names */
700 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
701 const struct xt_entry_target *t;
702
703 e = loc_cpu_entry + off;
704 if (copy_to_user(userptr + off, e,
705 offsetof(struct arpt_entry, counters)) ||
706 copy_to_user(userptr + off
707 + offsetof(struct arpt_entry, counters),
708 &counters[num],
709 sizeof(counters[num]))) {
710 ret = -EFAULT;
711 goto free_counters;
712 }
713
714 t = arpt_get_target_c(e);
715 if (xt_target_to_user(t, userptr + off + e->target_offset)) {
716 ret = -EFAULT;
717 goto free_counters;
718 }
719 }
720
721 free_counters:
722 vfree(counters);
723 return ret;
724 }
725
get_info(struct net * net,void __user * user,const int * len)726 static int get_info(struct net *net, void __user *user, const int *len)
727 {
728 char name[XT_TABLE_MAXNAMELEN];
729 struct xt_table *t;
730 int ret;
731
732 if (*len != sizeof(struct arpt_getinfo))
733 return -EINVAL;
734
735 if (copy_from_user(name, user, sizeof(name)) != 0)
736 return -EFAULT;
737
738 name[XT_TABLE_MAXNAMELEN-1] = '\0';
739 t = xt_request_find_table_lock(net, NFPROTO_ARP, name);
740 if (!IS_ERR(t)) {
741 struct arpt_getinfo info;
742 const struct xt_table_info *private = t->private;
743
744 memset(&info, 0, sizeof(info));
745 info.valid_hooks = t->valid_hooks;
746 memcpy(info.hook_entry, private->hook_entry,
747 sizeof(info.hook_entry));
748 memcpy(info.underflow, private->underflow,
749 sizeof(info.underflow));
750 info.num_entries = private->number;
751 info.size = private->size;
752 strscpy(info.name, name);
753
754 if (copy_to_user(user, &info, *len) != 0)
755 ret = -EFAULT;
756 else
757 ret = 0;
758 xt_table_unlock(t);
759 module_put(t->me);
760 } else
761 ret = PTR_ERR(t);
762
763 return ret;
764 }
765
get_entries(struct net * net,struct arpt_get_entries __user * uptr,const int * len)766 static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
767 const int *len)
768 {
769 int ret;
770 struct arpt_get_entries get;
771 struct xt_table *t;
772
773 if (*len < sizeof(get))
774 return -EINVAL;
775 if (copy_from_user(&get, uptr, sizeof(get)) != 0)
776 return -EFAULT;
777 if (*len != sizeof(struct arpt_get_entries) + get.size)
778 return -EINVAL;
779
780 get.name[sizeof(get.name) - 1] = '\0';
781
782 t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
783 if (!IS_ERR(t)) {
784 const struct xt_table_info *private = t->private;
785
786 if (get.size == private->size)
787 ret = copy_entries_to_user(private->size,
788 t, uptr->entrytable);
789 else
790 ret = -EAGAIN;
791
792 module_put(t->me);
793 xt_table_unlock(t);
794 } else
795 ret = PTR_ERR(t);
796
797 return ret;
798 }
799
__do_replace(struct net * net,const char * name,unsigned int valid_hooks,struct xt_table_info * newinfo,unsigned int num_counters,void __user * counters_ptr)800 static int __do_replace(struct net *net, const char *name,
801 unsigned int valid_hooks,
802 struct xt_table_info *newinfo,
803 unsigned int num_counters,
804 void __user *counters_ptr)
805 {
806 int ret;
807 struct xt_table *t;
808 struct xt_table_info *oldinfo;
809 struct xt_counters *counters;
810 void *loc_cpu_old_entry;
811 struct arpt_entry *iter;
812
813 ret = 0;
814 counters = xt_counters_alloc(num_counters);
815 if (!counters) {
816 ret = -ENOMEM;
817 goto out;
818 }
819
820 t = xt_request_find_table_lock(net, NFPROTO_ARP, name);
821 if (IS_ERR(t)) {
822 ret = PTR_ERR(t);
823 goto free_newinfo_counters_untrans;
824 }
825
826 /* You lied! */
827 if (valid_hooks != t->valid_hooks) {
828 ret = -EINVAL;
829 goto put_module;
830 }
831
832 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret);
833 if (!oldinfo)
834 goto put_module;
835
836 /* Update module usage count based on number of rules */
837 if ((oldinfo->number > oldinfo->initial_entries) ||
838 (newinfo->number <= oldinfo->initial_entries))
839 module_put(t->me);
840 if ((oldinfo->number > oldinfo->initial_entries) &&
841 (newinfo->number <= oldinfo->initial_entries))
842 module_put(t->me);
843
844 xt_table_unlock(t);
845
846 get_old_counters(oldinfo, counters);
847
848 /* Decrease module usage counts and free resource */
849 loc_cpu_old_entry = oldinfo->entries;
850 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
851 cleanup_entry(iter, net);
852
853 xt_free_table_info(oldinfo);
854 if (copy_to_user(counters_ptr, counters,
855 sizeof(struct xt_counters) * num_counters) != 0) {
856 /* Silent error, can't fail, new table is already in place */
857 net_warn_ratelimited("arptables: counters copy to user failed while replacing table\n");
858 }
859 vfree(counters);
860 return ret;
861
862 put_module:
863 module_put(t->me);
864 xt_table_unlock(t);
865 free_newinfo_counters_untrans:
866 vfree(counters);
867 out:
868 return ret;
869 }
870
do_replace(struct net * net,sockptr_t arg,unsigned int len)871 static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
872 {
873 int ret;
874 struct arpt_replace tmp;
875 struct xt_table_info *newinfo;
876 void *loc_cpu_entry;
877 struct arpt_entry *iter;
878
879 if (len < sizeof(tmp))
880 return -EINVAL;
881 if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
882 return -EFAULT;
883
884 /* overflow check */
885 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
886 return -ENOMEM;
887 if (tmp.num_counters == 0)
888 return -EINVAL;
889 if ((u64)len < (u64)tmp.size + sizeof(tmp))
890 return -EINVAL;
891
892 tmp.name[sizeof(tmp.name)-1] = 0;
893
894 newinfo = xt_alloc_table_info(tmp.size);
895 if (!newinfo)
896 return -ENOMEM;
897
898 loc_cpu_entry = newinfo->entries;
899 if (copy_from_sockptr_offset(loc_cpu_entry, arg, sizeof(tmp),
900 tmp.size) != 0) {
901 ret = -EFAULT;
902 goto free_newinfo;
903 }
904
905 ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
906 if (ret != 0)
907 goto free_newinfo;
908
909 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
910 tmp.num_counters, tmp.counters);
911 if (ret)
912 goto free_newinfo_untrans;
913 return 0;
914
915 free_newinfo_untrans:
916 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
917 cleanup_entry(iter, net);
918 free_newinfo:
919 xt_free_table_info(newinfo);
920 return ret;
921 }
922
do_add_counters(struct net * net,sockptr_t arg,unsigned int len)923 static int do_add_counters(struct net *net, sockptr_t arg, unsigned int len)
924 {
925 unsigned int i;
926 struct xt_counters_info tmp;
927 struct xt_counters *paddc;
928 struct xt_table *t;
929 const struct xt_table_info *private;
930 int ret = 0;
931 struct arpt_entry *iter;
932 unsigned int addend;
933
934 paddc = xt_copy_counters(arg, len, &tmp);
935 if (IS_ERR(paddc))
936 return PTR_ERR(paddc);
937
938 t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name);
939 if (IS_ERR(t)) {
940 ret = PTR_ERR(t);
941 goto free;
942 }
943
944 local_bh_disable();
945 private = t->private;
946 if (private->number != tmp.num_counters) {
947 ret = -EINVAL;
948 goto unlock_up_free;
949 }
950
951 i = 0;
952
953 addend = xt_write_recseq_begin();
954 xt_entry_foreach(iter, private->entries, private->size) {
955 struct xt_counters *tmp;
956
957 tmp = xt_get_this_cpu_counter(&iter->counters);
958 ADD_COUNTER(*tmp, paddc[i].bcnt, paddc[i].pcnt);
959 ++i;
960 }
961 xt_write_recseq_end(addend);
962 unlock_up_free:
963 local_bh_enable();
964 xt_table_unlock(t);
965 module_put(t->me);
966 free:
967 vfree(paddc);
968
969 return ret;
970 }
971
do_arpt_set_ctl(struct sock * sk,int cmd,sockptr_t arg,unsigned int len)972 static int do_arpt_set_ctl(struct sock *sk, int cmd, sockptr_t arg,
973 unsigned int len)
974 {
975 int ret;
976
977 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
978 return -EPERM;
979 if (!xt_compat_check())
980 return -EPERM;
981
982 switch (cmd) {
983 case ARPT_SO_SET_REPLACE:
984 ret = do_replace(sock_net(sk), arg, len);
985 break;
986
987 case ARPT_SO_SET_ADD_COUNTERS:
988 ret = do_add_counters(sock_net(sk), arg, len);
989 break;
990
991 default:
992 ret = -EINVAL;
993 }
994
995 return ret;
996 }
997
do_arpt_get_ctl(struct sock * sk,int cmd,void __user * user,int * len)998 static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
999 {
1000 int ret;
1001
1002 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
1003 return -EPERM;
1004 if (!xt_compat_check())
1005 return -EPERM;
1006
1007 switch (cmd) {
1008 case ARPT_SO_GET_INFO:
1009 ret = get_info(sock_net(sk), user, len);
1010 break;
1011
1012 case ARPT_SO_GET_ENTRIES:
1013 ret = get_entries(sock_net(sk), user, len);
1014 break;
1015
1016 case ARPT_SO_GET_REVISION_TARGET: {
1017 struct xt_get_revision rev;
1018
1019 if (*len != sizeof(rev)) {
1020 ret = -EINVAL;
1021 break;
1022 }
1023 if (copy_from_user(&rev, user, sizeof(rev)) != 0) {
1024 ret = -EFAULT;
1025 break;
1026 }
1027 rev.name[sizeof(rev.name)-1] = 0;
1028
1029 try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name,
1030 rev.revision, 1, &ret),
1031 "arpt_%s", rev.name);
1032 break;
1033 }
1034
1035 default:
1036 ret = -EINVAL;
1037 }
1038
1039 return ret;
1040 }
1041
__arpt_unregister_table(struct net * net,struct xt_table * table)1042 static void __arpt_unregister_table(struct net *net, struct xt_table *table)
1043 {
1044 struct xt_table_info *private = table->private;
1045 struct module *table_owner = table->me;
1046 void *loc_cpu_entry;
1047 struct arpt_entry *iter;
1048
1049 /* Decrease module usage counts and free resources */
1050 loc_cpu_entry = private->entries;
1051 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1052 cleanup_entry(iter, net);
1053 if (private->number > private->initial_entries)
1054 module_put(table_owner);
1055 xt_free_table_info(private);
1056 kfree(table);
1057 }
1058
arpt_register_table(struct net * net,const struct xt_table * table,const struct arpt_replace * repl,const struct nf_hook_ops * template_ops)1059 int arpt_register_table(struct net *net,
1060 const struct xt_table *table,
1061 const struct arpt_replace *repl,
1062 const struct nf_hook_ops *template_ops)
1063 {
1064 struct xt_table_info bootstrap = {0};
1065 struct xt_table_info *newinfo;
1066 struct xt_table *new_table;
1067 void *loc_cpu_entry;
1068 int ret;
1069
1070 newinfo = xt_alloc_table_info(repl->size);
1071 if (!newinfo)
1072 return -ENOMEM;
1073
1074 loc_cpu_entry = newinfo->entries;
1075 memcpy(loc_cpu_entry, repl->entries, repl->size);
1076
1077 ret = translate_table(net, newinfo, loc_cpu_entry, repl);
1078 if (ret != 0) {
1079 xt_free_table_info(newinfo);
1080 return ret;
1081 }
1082
1083 new_table = xt_register_table(net, table, template_ops, &bootstrap, newinfo);
1084 if (IS_ERR(new_table)) {
1085 struct arpt_entry *iter;
1086
1087 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1088 cleanup_entry(iter, net);
1089 xt_free_table_info(newinfo);
1090 return PTR_ERR(new_table);
1091 }
1092
1093 return ret;
1094 }
1095
arpt_unregister_table(struct net * net,const char * name)1096 void arpt_unregister_table(struct net *net, const char *name)
1097 {
1098 struct xt_table *table = xt_unregister_table_exit(net, NFPROTO_ARP, name);
1099
1100 if (table)
1101 __arpt_unregister_table(net, table);
1102 }
1103
1104 /* The built-in targets: standard (NULL) and error. */
1105 static struct xt_target arpt_builtin_tg[] __read_mostly = {
1106 {
1107 .name = XT_STANDARD_TARGET,
1108 .targetsize = sizeof(int),
1109 .family = NFPROTO_ARP,
1110 },
1111 {
1112 .name = XT_ERROR_TARGET,
1113 .target = arpt_error,
1114 .targetsize = XT_FUNCTION_MAXNAMELEN,
1115 .family = NFPROTO_ARP,
1116 },
1117 };
1118
1119 static struct nf_sockopt_ops arpt_sockopts = {
1120 .pf = PF_INET,
1121 .set_optmin = ARPT_BASE_CTL,
1122 .set_optmax = ARPT_SO_SET_MAX+1,
1123 .set = do_arpt_set_ctl,
1124 .get_optmin = ARPT_BASE_CTL,
1125 .get_optmax = ARPT_SO_GET_MAX+1,
1126 .get = do_arpt_get_ctl,
1127 .owner = THIS_MODULE,
1128 };
1129
arp_tables_net_init(struct net * net)1130 static int __net_init arp_tables_net_init(struct net *net)
1131 {
1132 return xt_proto_init(net, NFPROTO_ARP);
1133 }
1134
arp_tables_net_exit(struct net * net)1135 static void __net_exit arp_tables_net_exit(struct net *net)
1136 {
1137 xt_proto_fini(net, NFPROTO_ARP);
1138 }
1139
1140 static struct pernet_operations arp_tables_net_ops = {
1141 .init = arp_tables_net_init,
1142 .exit = arp_tables_net_exit,
1143 };
1144
arp_tables_init(void)1145 static int __init arp_tables_init(void)
1146 {
1147 int ret;
1148
1149 ret = register_pernet_subsys(&arp_tables_net_ops);
1150 if (ret < 0)
1151 goto err1;
1152
1153 /* No one else will be downing sem now, so we won't sleep */
1154 ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg));
1155 if (ret < 0)
1156 goto err2;
1157
1158 /* Register setsockopt */
1159 ret = nf_register_sockopt(&arpt_sockopts);
1160 if (ret < 0)
1161 goto err4;
1162
1163 return 0;
1164
1165 err4:
1166 xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg));
1167 err2:
1168 unregister_pernet_subsys(&arp_tables_net_ops);
1169 err1:
1170 return ret;
1171 }
1172
arp_tables_fini(void)1173 static void __exit arp_tables_fini(void)
1174 {
1175 nf_unregister_sockopt(&arpt_sockopts);
1176 xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg));
1177 unregister_pernet_subsys(&arp_tables_net_ops);
1178 }
1179
1180 EXPORT_SYMBOL(arpt_register_table);
1181 EXPORT_SYMBOL(arpt_unregister_table);
1182 EXPORT_SYMBOL(arpt_do_table);
1183
1184 module_init(arp_tables_init);
1185 module_exit(arp_tables_fini);
1186