1 /* 2 * Packet matching code for ARP packets. 3 * 4 * Based heavily, if not almost entirely, upon ip_tables.c framework. 5 * 6 * Some ARP specific bits are: 7 * 8 * Copyright (C) 2002 David S. Miller (davem@redhat.com) 9 * Copyright (C) 2006-2009 Patrick McHardy <kaber@trash.net> 10 * 11 */ 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 #include <linux/kernel.h> 14 #include <linux/skbuff.h> 15 #include <linux/netdevice.h> 16 #include <linux/capability.h> 17 #include <linux/if_arp.h> 18 #include <linux/kmod.h> 19 #include <linux/vmalloc.h> 20 #include <linux/proc_fs.h> 21 #include <linux/module.h> 22 #include <linux/init.h> 23 #include <linux/mutex.h> 24 #include <linux/err.h> 25 #include <net/compat.h> 26 #include <net/sock.h> 27 #include <asm/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 37 /*#define DEBUG_ARP_TABLES*/ 38 /*#define DEBUG_ARP_TABLES_USER*/ 39 40 #ifdef DEBUG_ARP_TABLES 41 #define dprintf(format, args...) printk(format , ## args) 42 #else 43 #define dprintf(format, args...) 44 #endif 45 46 #ifdef DEBUG_ARP_TABLES_USER 47 #define duprintf(format, args...) printk(format , ## args) 48 #else 49 #define duprintf(format, args...) 50 #endif 51 52 #ifdef CONFIG_NETFILTER_DEBUG 53 #define ARP_NF_ASSERT(x) WARN_ON(!(x)) 54 #else 55 #define ARP_NF_ASSERT(x) 56 #endif 57 58 void *arpt_alloc_initial_table(const struct xt_table *info) 59 { 60 return xt_alloc_initial_table(arpt, ARPT); 61 } 62 EXPORT_SYMBOL_GPL(arpt_alloc_initial_table); 63 64 static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 65 const char *hdr_addr, int len) 66 { 67 int i, ret; 68 69 if (len > ARPT_DEV_ADDR_LEN_MAX) 70 len = ARPT_DEV_ADDR_LEN_MAX; 71 72 ret = 0; 73 for (i = 0; i < len; i++) 74 ret |= (hdr_addr[i] ^ ap->addr[i]) & ap->mask[i]; 75 76 return ret != 0; 77 } 78 79 /* 80 * Unfortunately, _b and _mask are not aligned to an int (or long int) 81 * Some arches dont care, unrolling the loop is a win on them. 82 * For other arches, we only have a 16bit alignement. 83 */ 84 static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) 85 { 86 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 87 unsigned long ret = ifname_compare_aligned(_a, _b, _mask); 88 #else 89 unsigned long ret = 0; 90 const u16 *a = (const u16 *)_a; 91 const u16 *b = (const u16 *)_b; 92 const u16 *mask = (const u16 *)_mask; 93 int i; 94 95 for (i = 0; i < IFNAMSIZ/sizeof(u16); i++) 96 ret |= (a[i] ^ b[i]) & mask[i]; 97 #endif 98 return ret; 99 } 100 101 /* Returns whether packet matches rule or not. */ 102 static inline int arp_packet_match(const struct arphdr *arphdr, 103 struct net_device *dev, 104 const char *indev, 105 const char *outdev, 106 const struct arpt_arp *arpinfo) 107 { 108 const char *arpptr = (char *)(arphdr + 1); 109 const char *src_devaddr, *tgt_devaddr; 110 __be32 src_ipaddr, tgt_ipaddr; 111 long ret; 112 113 #define FWINV(bool, invflg) ((bool) ^ !!(arpinfo->invflags & (invflg))) 114 115 if (FWINV((arphdr->ar_op & arpinfo->arpop_mask) != arpinfo->arpop, 116 ARPT_INV_ARPOP)) { 117 dprintf("ARP operation field mismatch.\n"); 118 dprintf("ar_op: %04x info->arpop: %04x info->arpop_mask: %04x\n", 119 arphdr->ar_op, arpinfo->arpop, arpinfo->arpop_mask); 120 return 0; 121 } 122 123 if (FWINV((arphdr->ar_hrd & arpinfo->arhrd_mask) != arpinfo->arhrd, 124 ARPT_INV_ARPHRD)) { 125 dprintf("ARP hardware address format mismatch.\n"); 126 dprintf("ar_hrd: %04x info->arhrd: %04x info->arhrd_mask: %04x\n", 127 arphdr->ar_hrd, arpinfo->arhrd, arpinfo->arhrd_mask); 128 return 0; 129 } 130 131 if (FWINV((arphdr->ar_pro & arpinfo->arpro_mask) != arpinfo->arpro, 132 ARPT_INV_ARPPRO)) { 133 dprintf("ARP protocol address format mismatch.\n"); 134 dprintf("ar_pro: %04x info->arpro: %04x info->arpro_mask: %04x\n", 135 arphdr->ar_pro, arpinfo->arpro, arpinfo->arpro_mask); 136 return 0; 137 } 138 139 if (FWINV((arphdr->ar_hln & arpinfo->arhln_mask) != arpinfo->arhln, 140 ARPT_INV_ARPHLN)) { 141 dprintf("ARP hardware address length mismatch.\n"); 142 dprintf("ar_hln: %02x info->arhln: %02x info->arhln_mask: %02x\n", 143 arphdr->ar_hln, arpinfo->arhln, arpinfo->arhln_mask); 144 return 0; 145 } 146 147 src_devaddr = arpptr; 148 arpptr += dev->addr_len; 149 memcpy(&src_ipaddr, arpptr, sizeof(u32)); 150 arpptr += sizeof(u32); 151 tgt_devaddr = arpptr; 152 arpptr += dev->addr_len; 153 memcpy(&tgt_ipaddr, arpptr, sizeof(u32)); 154 155 if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len), 156 ARPT_INV_SRCDEVADDR) || 157 FWINV(arp_devaddr_compare(&arpinfo->tgt_devaddr, tgt_devaddr, dev->addr_len), 158 ARPT_INV_TGTDEVADDR)) { 159 dprintf("Source or target device address mismatch.\n"); 160 161 return 0; 162 } 163 164 if (FWINV((src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr, 165 ARPT_INV_SRCIP) || 166 FWINV(((tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr), 167 ARPT_INV_TGTIP)) { 168 dprintf("Source or target IP address mismatch.\n"); 169 170 dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n", 171 &src_ipaddr, 172 &arpinfo->smsk.s_addr, 173 &arpinfo->src.s_addr, 174 arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : ""); 175 dprintf("TGT: %pI4 Mask: %pI4 Target: %pI4.%s\n", 176 &tgt_ipaddr, 177 &arpinfo->tmsk.s_addr, 178 &arpinfo->tgt.s_addr, 179 arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : ""); 180 return 0; 181 } 182 183 /* Look for ifname matches. */ 184 ret = ifname_compare(indev, arpinfo->iniface, arpinfo->iniface_mask); 185 186 if (FWINV(ret != 0, ARPT_INV_VIA_IN)) { 187 dprintf("VIA in mismatch (%s vs %s).%s\n", 188 indev, arpinfo->iniface, 189 arpinfo->invflags & ARPT_INV_VIA_IN ? " (INV)" : ""); 190 return 0; 191 } 192 193 ret = ifname_compare(outdev, arpinfo->outiface, arpinfo->outiface_mask); 194 195 if (FWINV(ret != 0, ARPT_INV_VIA_OUT)) { 196 dprintf("VIA out mismatch (%s vs %s).%s\n", 197 outdev, arpinfo->outiface, 198 arpinfo->invflags & ARPT_INV_VIA_OUT ? " (INV)" : ""); 199 return 0; 200 } 201 202 return 1; 203 #undef FWINV 204 } 205 206 static inline int arp_checkentry(const struct arpt_arp *arp) 207 { 208 if (arp->flags & ~ARPT_F_MASK) { 209 duprintf("Unknown flag bits set: %08X\n", 210 arp->flags & ~ARPT_F_MASK); 211 return 0; 212 } 213 if (arp->invflags & ~ARPT_INV_MASK) { 214 duprintf("Unknown invflag bits set: %08X\n", 215 arp->invflags & ~ARPT_INV_MASK); 216 return 0; 217 } 218 219 return 1; 220 } 221 222 static unsigned int 223 arpt_error(struct sk_buff *skb, const struct xt_action_param *par) 224 { 225 net_err_ratelimited("arp_tables: error: '%s'\n", 226 (const char *)par->targinfo); 227 228 return NF_DROP; 229 } 230 231 static inline const struct xt_entry_target * 232 arpt_get_target_c(const struct arpt_entry *e) 233 { 234 return arpt_get_target((struct arpt_entry *)e); 235 } 236 237 static inline struct arpt_entry * 238 get_entry(const void *base, unsigned int offset) 239 { 240 return (struct arpt_entry *)(base + offset); 241 } 242 243 static inline 244 struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry) 245 { 246 return (void *)entry + entry->next_offset; 247 } 248 249 unsigned int arpt_do_table(struct sk_buff *skb, 250 const struct nf_hook_state *state, 251 struct xt_table *table) 252 { 253 unsigned int hook = state->hook; 254 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 255 unsigned int verdict = NF_DROP; 256 const struct arphdr *arp; 257 struct arpt_entry *e, **jumpstack; 258 const char *indev, *outdev; 259 const void *table_base; 260 unsigned int cpu, stackidx = 0; 261 const struct xt_table_info *private; 262 struct xt_action_param acpar; 263 unsigned int addend; 264 265 if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) 266 return NF_DROP; 267 268 indev = state->in ? state->in->name : nulldevname; 269 outdev = state->out ? state->out->name : nulldevname; 270 271 local_bh_disable(); 272 addend = xt_write_recseq_begin(); 273 private = table->private; 274 cpu = smp_processor_id(); 275 /* 276 * Ensure we load private-> members after we've fetched the base 277 * pointer. 278 */ 279 smp_read_barrier_depends(); 280 table_base = private->entries; 281 jumpstack = (struct arpt_entry **)private->jumpstack[cpu]; 282 283 /* No TEE support for arptables, so no need to switch to alternate 284 * stack. All targets that reenter must return absolute verdicts. 285 */ 286 e = get_entry(table_base, private->hook_entry[hook]); 287 288 acpar.net = state->net; 289 acpar.in = state->in; 290 acpar.out = state->out; 291 acpar.hooknum = hook; 292 acpar.family = NFPROTO_ARP; 293 acpar.hotdrop = false; 294 295 arp = arp_hdr(skb); 296 do { 297 const struct xt_entry_target *t; 298 struct xt_counters *counter; 299 300 if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { 301 e = arpt_next_entry(e); 302 continue; 303 } 304 305 counter = xt_get_this_cpu_counter(&e->counters); 306 ADD_COUNTER(*counter, arp_hdr_len(skb->dev), 1); 307 308 t = arpt_get_target_c(e); 309 310 /* Standard target? */ 311 if (!t->u.kernel.target->target) { 312 int v; 313 314 v = ((struct xt_standard_target *)t)->verdict; 315 if (v < 0) { 316 /* Pop from stack? */ 317 if (v != XT_RETURN) { 318 verdict = (unsigned int)(-v) - 1; 319 break; 320 } 321 if (stackidx == 0) { 322 e = get_entry(table_base, 323 private->underflow[hook]); 324 } else { 325 e = jumpstack[--stackidx]; 326 e = arpt_next_entry(e); 327 } 328 continue; 329 } 330 if (table_base + v 331 != arpt_next_entry(e)) { 332 jumpstack[stackidx++] = e; 333 } 334 335 e = get_entry(table_base, v); 336 continue; 337 } 338 339 acpar.target = t->u.kernel.target; 340 acpar.targinfo = t->data; 341 verdict = t->u.kernel.target->target(skb, &acpar); 342 343 /* Target might have changed stuff. */ 344 arp = arp_hdr(skb); 345 346 if (verdict == XT_CONTINUE) 347 e = arpt_next_entry(e); 348 else 349 /* Verdict */ 350 break; 351 } while (!acpar.hotdrop); 352 xt_write_recseq_end(addend); 353 local_bh_enable(); 354 355 if (acpar.hotdrop) 356 return NF_DROP; 357 else 358 return verdict; 359 } 360 361 /* All zeroes == unconditional rule. */ 362 static inline bool unconditional(const struct arpt_arp *arp) 363 { 364 static const struct arpt_arp uncond; 365 366 return memcmp(arp, &uncond, sizeof(uncond)) == 0; 367 } 368 369 /* Figures out from what hook each rule can be called: returns 0 if 370 * there are loops. Puts hook bitmask in comefrom. 371 */ 372 static int mark_source_chains(const struct xt_table_info *newinfo, 373 unsigned int valid_hooks, void *entry0) 374 { 375 unsigned int hook; 376 377 /* No recursion; use packet counter to save back ptrs (reset 378 * to 0 as we leave), and comefrom to save source hook bitmask. 379 */ 380 for (hook = 0; hook < NF_ARP_NUMHOOKS; hook++) { 381 unsigned int pos = newinfo->hook_entry[hook]; 382 struct arpt_entry *e 383 = (struct arpt_entry *)(entry0 + pos); 384 385 if (!(valid_hooks & (1 << hook))) 386 continue; 387 388 /* Set initial back pointer. */ 389 e->counters.pcnt = pos; 390 391 for (;;) { 392 const struct xt_standard_target *t 393 = (void *)arpt_get_target_c(e); 394 int visited = e->comefrom & (1 << hook); 395 396 if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) { 397 pr_notice("arptables: loop hook %u pos %u %08X.\n", 398 hook, pos, e->comefrom); 399 return 0; 400 } 401 e->comefrom 402 |= ((1 << hook) | (1 << NF_ARP_NUMHOOKS)); 403 404 /* Unconditional return/END. */ 405 if ((e->target_offset == sizeof(struct arpt_entry) && 406 (strcmp(t->target.u.user.name, 407 XT_STANDARD_TARGET) == 0) && 408 t->verdict < 0 && unconditional(&e->arp)) || 409 visited) { 410 unsigned int oldpos, size; 411 412 if ((strcmp(t->target.u.user.name, 413 XT_STANDARD_TARGET) == 0) && 414 t->verdict < -NF_MAX_VERDICT - 1) { 415 duprintf("mark_source_chains: bad " 416 "negative verdict (%i)\n", 417 t->verdict); 418 return 0; 419 } 420 421 /* Return: backtrack through the last 422 * big jump. 423 */ 424 do { 425 e->comefrom ^= (1<<NF_ARP_NUMHOOKS); 426 oldpos = pos; 427 pos = e->counters.pcnt; 428 e->counters.pcnt = 0; 429 430 /* We're at the start. */ 431 if (pos == oldpos) 432 goto next; 433 434 e = (struct arpt_entry *) 435 (entry0 + pos); 436 } while (oldpos == pos + e->next_offset); 437 438 /* Move along one */ 439 size = e->next_offset; 440 e = (struct arpt_entry *) 441 (entry0 + pos + size); 442 e->counters.pcnt = pos; 443 pos += size; 444 } else { 445 int newpos = t->verdict; 446 447 if (strcmp(t->target.u.user.name, 448 XT_STANDARD_TARGET) == 0 && 449 newpos >= 0) { 450 if (newpos > newinfo->size - 451 sizeof(struct arpt_entry)) { 452 duprintf("mark_source_chains: " 453 "bad verdict (%i)\n", 454 newpos); 455 return 0; 456 } 457 458 /* This a jump; chase it. */ 459 duprintf("Jump rule %u -> %u\n", 460 pos, newpos); 461 } else { 462 /* ... this is a fallthru */ 463 newpos = pos + e->next_offset; 464 } 465 e = (struct arpt_entry *) 466 (entry0 + newpos); 467 e->counters.pcnt = pos; 468 pos = newpos; 469 } 470 } 471 next: 472 duprintf("Finished chain %u\n", hook); 473 } 474 return 1; 475 } 476 477 static inline int check_entry(const struct arpt_entry *e, const char *name) 478 { 479 const struct xt_entry_target *t; 480 481 if (!arp_checkentry(&e->arp)) { 482 duprintf("arp_tables: arp check failed %p %s.\n", e, name); 483 return -EINVAL; 484 } 485 486 if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset) 487 return -EINVAL; 488 489 t = arpt_get_target_c(e); 490 if (e->target_offset + t->u.target_size > e->next_offset) 491 return -EINVAL; 492 493 return 0; 494 } 495 496 static inline int check_target(struct arpt_entry *e, const char *name) 497 { 498 struct xt_entry_target *t = arpt_get_target(e); 499 int ret; 500 struct xt_tgchk_param par = { 501 .table = name, 502 .entryinfo = e, 503 .target = t->u.kernel.target, 504 .targinfo = t->data, 505 .hook_mask = e->comefrom, 506 .family = NFPROTO_ARP, 507 }; 508 509 ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false); 510 if (ret < 0) { 511 duprintf("arp_tables: check failed for `%s'.\n", 512 t->u.kernel.target->name); 513 return ret; 514 } 515 return 0; 516 } 517 518 static inline int 519 find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) 520 { 521 struct xt_entry_target *t; 522 struct xt_target *target; 523 int ret; 524 525 ret = check_entry(e, name); 526 if (ret) 527 return ret; 528 529 e->counters.pcnt = xt_percpu_counter_alloc(); 530 if (IS_ERR_VALUE(e->counters.pcnt)) 531 return -ENOMEM; 532 533 t = arpt_get_target(e); 534 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name, 535 t->u.user.revision); 536 if (IS_ERR(target)) { 537 duprintf("find_check_entry: `%s' not found\n", t->u.user.name); 538 ret = PTR_ERR(target); 539 goto out; 540 } 541 t->u.kernel.target = target; 542 543 ret = check_target(e, name); 544 if (ret) 545 goto err; 546 return 0; 547 err: 548 module_put(t->u.kernel.target->me); 549 out: 550 xt_percpu_counter_free(e->counters.pcnt); 551 552 return ret; 553 } 554 555 static bool check_underflow(const struct arpt_entry *e) 556 { 557 const struct xt_entry_target *t; 558 unsigned int verdict; 559 560 if (!unconditional(&e->arp)) 561 return false; 562 t = arpt_get_target_c(e); 563 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) 564 return false; 565 verdict = ((struct xt_standard_target *)t)->verdict; 566 verdict = -verdict - 1; 567 return verdict == NF_DROP || verdict == NF_ACCEPT; 568 } 569 570 static inline int check_entry_size_and_hooks(struct arpt_entry *e, 571 struct xt_table_info *newinfo, 572 const unsigned char *base, 573 const unsigned char *limit, 574 const unsigned int *hook_entries, 575 const unsigned int *underflows, 576 unsigned int valid_hooks) 577 { 578 unsigned int h; 579 580 if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 || 581 (unsigned char *)e + sizeof(struct arpt_entry) >= limit) { 582 duprintf("Bad offset %p\n", e); 583 return -EINVAL; 584 } 585 586 if (e->next_offset 587 < sizeof(struct arpt_entry) + sizeof(struct xt_entry_target)) { 588 duprintf("checking: element %p size %u\n", 589 e, e->next_offset); 590 return -EINVAL; 591 } 592 593 /* Check hooks & underflows */ 594 for (h = 0; h < NF_ARP_NUMHOOKS; h++) { 595 if (!(valid_hooks & (1 << h))) 596 continue; 597 if ((unsigned char *)e - base == hook_entries[h]) 598 newinfo->hook_entry[h] = hook_entries[h]; 599 if ((unsigned char *)e - base == underflows[h]) { 600 if (!check_underflow(e)) { 601 pr_err("Underflows must be unconditional and " 602 "use the STANDARD target with " 603 "ACCEPT/DROP\n"); 604 return -EINVAL; 605 } 606 newinfo->underflow[h] = underflows[h]; 607 } 608 } 609 610 /* Clear counters and comefrom */ 611 e->counters = ((struct xt_counters) { 0, 0 }); 612 e->comefrom = 0; 613 return 0; 614 } 615 616 static inline void cleanup_entry(struct arpt_entry *e) 617 { 618 struct xt_tgdtor_param par; 619 struct xt_entry_target *t; 620 621 t = arpt_get_target(e); 622 par.target = t->u.kernel.target; 623 par.targinfo = t->data; 624 par.family = NFPROTO_ARP; 625 if (par.target->destroy != NULL) 626 par.target->destroy(&par); 627 module_put(par.target->me); 628 xt_percpu_counter_free(e->counters.pcnt); 629 } 630 631 /* Checks and translates the user-supplied table segment (held in 632 * newinfo). 633 */ 634 static int translate_table(struct xt_table_info *newinfo, void *entry0, 635 const struct arpt_replace *repl) 636 { 637 struct arpt_entry *iter; 638 unsigned int i; 639 int ret = 0; 640 641 newinfo->size = repl->size; 642 newinfo->number = repl->num_entries; 643 644 /* Init all hooks to impossible value. */ 645 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 646 newinfo->hook_entry[i] = 0xFFFFFFFF; 647 newinfo->underflow[i] = 0xFFFFFFFF; 648 } 649 650 duprintf("translate_table: size %u\n", newinfo->size); 651 i = 0; 652 653 /* Walk through entries, checking offsets. */ 654 xt_entry_foreach(iter, entry0, newinfo->size) { 655 ret = check_entry_size_and_hooks(iter, newinfo, entry0, 656 entry0 + repl->size, 657 repl->hook_entry, 658 repl->underflow, 659 repl->valid_hooks); 660 if (ret != 0) 661 break; 662 ++i; 663 if (strcmp(arpt_get_target(iter)->u.user.name, 664 XT_ERROR_TARGET) == 0) 665 ++newinfo->stacksize; 666 } 667 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); 668 if (ret != 0) 669 return ret; 670 671 if (i != repl->num_entries) { 672 duprintf("translate_table: %u not %u entries\n", 673 i, repl->num_entries); 674 return -EINVAL; 675 } 676 677 /* Check hooks all assigned */ 678 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 679 /* Only hooks which are valid */ 680 if (!(repl->valid_hooks & (1 << i))) 681 continue; 682 if (newinfo->hook_entry[i] == 0xFFFFFFFF) { 683 duprintf("Invalid hook entry %u %u\n", 684 i, repl->hook_entry[i]); 685 return -EINVAL; 686 } 687 if (newinfo->underflow[i] == 0xFFFFFFFF) { 688 duprintf("Invalid underflow %u %u\n", 689 i, repl->underflow[i]); 690 return -EINVAL; 691 } 692 } 693 694 if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) { 695 duprintf("Looping hook\n"); 696 return -ELOOP; 697 } 698 699 /* Finally, each sanity check must pass */ 700 i = 0; 701 xt_entry_foreach(iter, entry0, newinfo->size) { 702 ret = find_check_entry(iter, repl->name, repl->size); 703 if (ret != 0) 704 break; 705 ++i; 706 } 707 708 if (ret != 0) { 709 xt_entry_foreach(iter, entry0, newinfo->size) { 710 if (i-- == 0) 711 break; 712 cleanup_entry(iter); 713 } 714 return ret; 715 } 716 717 return ret; 718 } 719 720 static void get_counters(const struct xt_table_info *t, 721 struct xt_counters counters[]) 722 { 723 struct arpt_entry *iter; 724 unsigned int cpu; 725 unsigned int i; 726 727 for_each_possible_cpu(cpu) { 728 seqcount_t *s = &per_cpu(xt_recseq, cpu); 729 730 i = 0; 731 xt_entry_foreach(iter, t->entries, t->size) { 732 struct xt_counters *tmp; 733 u64 bcnt, pcnt; 734 unsigned int start; 735 736 tmp = xt_get_per_cpu_counter(&iter->counters, cpu); 737 do { 738 start = read_seqcount_begin(s); 739 bcnt = tmp->bcnt; 740 pcnt = tmp->pcnt; 741 } while (read_seqcount_retry(s, start)); 742 743 ADD_COUNTER(counters[i], bcnt, pcnt); 744 ++i; 745 } 746 } 747 } 748 749 static struct xt_counters *alloc_counters(const struct xt_table *table) 750 { 751 unsigned int countersize; 752 struct xt_counters *counters; 753 const struct xt_table_info *private = table->private; 754 755 /* We need atomic snapshot of counters: rest doesn't change 756 * (other than comefrom, which userspace doesn't care 757 * about). 758 */ 759 countersize = sizeof(struct xt_counters) * private->number; 760 counters = vzalloc(countersize); 761 762 if (counters == NULL) 763 return ERR_PTR(-ENOMEM); 764 765 get_counters(private, counters); 766 767 return counters; 768 } 769 770 static int copy_entries_to_user(unsigned int total_size, 771 const struct xt_table *table, 772 void __user *userptr) 773 { 774 unsigned int off, num; 775 const struct arpt_entry *e; 776 struct xt_counters *counters; 777 struct xt_table_info *private = table->private; 778 int ret = 0; 779 void *loc_cpu_entry; 780 781 counters = alloc_counters(table); 782 if (IS_ERR(counters)) 783 return PTR_ERR(counters); 784 785 loc_cpu_entry = private->entries; 786 /* ... then copy entire thing ... */ 787 if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { 788 ret = -EFAULT; 789 goto free_counters; 790 } 791 792 /* FIXME: use iterator macros --RR */ 793 /* ... then go back and fix counters and names */ 794 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ 795 const struct xt_entry_target *t; 796 797 e = (struct arpt_entry *)(loc_cpu_entry + off); 798 if (copy_to_user(userptr + off 799 + offsetof(struct arpt_entry, counters), 800 &counters[num], 801 sizeof(counters[num])) != 0) { 802 ret = -EFAULT; 803 goto free_counters; 804 } 805 806 t = arpt_get_target_c(e); 807 if (copy_to_user(userptr + off + e->target_offset 808 + offsetof(struct xt_entry_target, 809 u.user.name), 810 t->u.kernel.target->name, 811 strlen(t->u.kernel.target->name)+1) != 0) { 812 ret = -EFAULT; 813 goto free_counters; 814 } 815 } 816 817 free_counters: 818 vfree(counters); 819 return ret; 820 } 821 822 #ifdef CONFIG_COMPAT 823 static void compat_standard_from_user(void *dst, const void *src) 824 { 825 int v = *(compat_int_t *)src; 826 827 if (v > 0) 828 v += xt_compat_calc_jump(NFPROTO_ARP, v); 829 memcpy(dst, &v, sizeof(v)); 830 } 831 832 static int compat_standard_to_user(void __user *dst, const void *src) 833 { 834 compat_int_t cv = *(int *)src; 835 836 if (cv > 0) 837 cv -= xt_compat_calc_jump(NFPROTO_ARP, cv); 838 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; 839 } 840 841 static int compat_calc_entry(const struct arpt_entry *e, 842 const struct xt_table_info *info, 843 const void *base, struct xt_table_info *newinfo) 844 { 845 const struct xt_entry_target *t; 846 unsigned int entry_offset; 847 int off, i, ret; 848 849 off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); 850 entry_offset = (void *)e - base; 851 852 t = arpt_get_target_c(e); 853 off += xt_compat_target_offset(t->u.kernel.target); 854 newinfo->size -= off; 855 ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off); 856 if (ret) 857 return ret; 858 859 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 860 if (info->hook_entry[i] && 861 (e < (struct arpt_entry *)(base + info->hook_entry[i]))) 862 newinfo->hook_entry[i] -= off; 863 if (info->underflow[i] && 864 (e < (struct arpt_entry *)(base + info->underflow[i]))) 865 newinfo->underflow[i] -= off; 866 } 867 return 0; 868 } 869 870 static int compat_table_info(const struct xt_table_info *info, 871 struct xt_table_info *newinfo) 872 { 873 struct arpt_entry *iter; 874 const void *loc_cpu_entry; 875 int ret; 876 877 if (!newinfo || !info) 878 return -EINVAL; 879 880 /* we dont care about newinfo->entries */ 881 memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); 882 newinfo->initial_entries = 0; 883 loc_cpu_entry = info->entries; 884 xt_compat_init_offsets(NFPROTO_ARP, info->number); 885 xt_entry_foreach(iter, loc_cpu_entry, info->size) { 886 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); 887 if (ret != 0) 888 return ret; 889 } 890 return 0; 891 } 892 #endif 893 894 static int get_info(struct net *net, void __user *user, 895 const int *len, int compat) 896 { 897 char name[XT_TABLE_MAXNAMELEN]; 898 struct xt_table *t; 899 int ret; 900 901 if (*len != sizeof(struct arpt_getinfo)) { 902 duprintf("length %u != %Zu\n", *len, 903 sizeof(struct arpt_getinfo)); 904 return -EINVAL; 905 } 906 907 if (copy_from_user(name, user, sizeof(name)) != 0) 908 return -EFAULT; 909 910 name[XT_TABLE_MAXNAMELEN-1] = '\0'; 911 #ifdef CONFIG_COMPAT 912 if (compat) 913 xt_compat_lock(NFPROTO_ARP); 914 #endif 915 t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name), 916 "arptable_%s", name); 917 if (!IS_ERR_OR_NULL(t)) { 918 struct arpt_getinfo info; 919 const struct xt_table_info *private = t->private; 920 #ifdef CONFIG_COMPAT 921 struct xt_table_info tmp; 922 923 if (compat) { 924 ret = compat_table_info(private, &tmp); 925 xt_compat_flush_offsets(NFPROTO_ARP); 926 private = &tmp; 927 } 928 #endif 929 memset(&info, 0, sizeof(info)); 930 info.valid_hooks = t->valid_hooks; 931 memcpy(info.hook_entry, private->hook_entry, 932 sizeof(info.hook_entry)); 933 memcpy(info.underflow, private->underflow, 934 sizeof(info.underflow)); 935 info.num_entries = private->number; 936 info.size = private->size; 937 strcpy(info.name, name); 938 939 if (copy_to_user(user, &info, *len) != 0) 940 ret = -EFAULT; 941 else 942 ret = 0; 943 xt_table_unlock(t); 944 module_put(t->me); 945 } else 946 ret = t ? PTR_ERR(t) : -ENOENT; 947 #ifdef CONFIG_COMPAT 948 if (compat) 949 xt_compat_unlock(NFPROTO_ARP); 950 #endif 951 return ret; 952 } 953 954 static int get_entries(struct net *net, struct arpt_get_entries __user *uptr, 955 const int *len) 956 { 957 int ret; 958 struct arpt_get_entries get; 959 struct xt_table *t; 960 961 if (*len < sizeof(get)) { 962 duprintf("get_entries: %u < %Zu\n", *len, sizeof(get)); 963 return -EINVAL; 964 } 965 if (copy_from_user(&get, uptr, sizeof(get)) != 0) 966 return -EFAULT; 967 if (*len != sizeof(struct arpt_get_entries) + get.size) { 968 duprintf("get_entries: %u != %Zu\n", *len, 969 sizeof(struct arpt_get_entries) + get.size); 970 return -EINVAL; 971 } 972 973 t = xt_find_table_lock(net, NFPROTO_ARP, get.name); 974 if (!IS_ERR_OR_NULL(t)) { 975 const struct xt_table_info *private = t->private; 976 977 duprintf("t->private->number = %u\n", 978 private->number); 979 if (get.size == private->size) 980 ret = copy_entries_to_user(private->size, 981 t, uptr->entrytable); 982 else { 983 duprintf("get_entries: I've got %u not %u!\n", 984 private->size, get.size); 985 ret = -EAGAIN; 986 } 987 module_put(t->me); 988 xt_table_unlock(t); 989 } else 990 ret = t ? PTR_ERR(t) : -ENOENT; 991 992 return ret; 993 } 994 995 static int __do_replace(struct net *net, const char *name, 996 unsigned int valid_hooks, 997 struct xt_table_info *newinfo, 998 unsigned int num_counters, 999 void __user *counters_ptr) 1000 { 1001 int ret; 1002 struct xt_table *t; 1003 struct xt_table_info *oldinfo; 1004 struct xt_counters *counters; 1005 void *loc_cpu_old_entry; 1006 struct arpt_entry *iter; 1007 1008 ret = 0; 1009 counters = vzalloc(num_counters * sizeof(struct xt_counters)); 1010 if (!counters) { 1011 ret = -ENOMEM; 1012 goto out; 1013 } 1014 1015 t = try_then_request_module(xt_find_table_lock(net, NFPROTO_ARP, name), 1016 "arptable_%s", name); 1017 if (IS_ERR_OR_NULL(t)) { 1018 ret = t ? PTR_ERR(t) : -ENOENT; 1019 goto free_newinfo_counters_untrans; 1020 } 1021 1022 /* You lied! */ 1023 if (valid_hooks != t->valid_hooks) { 1024 duprintf("Valid hook crap: %08X vs %08X\n", 1025 valid_hooks, t->valid_hooks); 1026 ret = -EINVAL; 1027 goto put_module; 1028 } 1029 1030 oldinfo = xt_replace_table(t, num_counters, newinfo, &ret); 1031 if (!oldinfo) 1032 goto put_module; 1033 1034 /* Update module usage count based on number of rules */ 1035 duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", 1036 oldinfo->number, oldinfo->initial_entries, newinfo->number); 1037 if ((oldinfo->number > oldinfo->initial_entries) || 1038 (newinfo->number <= oldinfo->initial_entries)) 1039 module_put(t->me); 1040 if ((oldinfo->number > oldinfo->initial_entries) && 1041 (newinfo->number <= oldinfo->initial_entries)) 1042 module_put(t->me); 1043 1044 /* Get the old counters, and synchronize with replace */ 1045 get_counters(oldinfo, counters); 1046 1047 /* Decrease module usage counts and free resource */ 1048 loc_cpu_old_entry = oldinfo->entries; 1049 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) 1050 cleanup_entry(iter); 1051 1052 xt_free_table_info(oldinfo); 1053 if (copy_to_user(counters_ptr, counters, 1054 sizeof(struct xt_counters) * num_counters) != 0) { 1055 /* Silent error, can't fail, new table is already in place */ 1056 net_warn_ratelimited("arptables: counters copy to user failed while replacing table\n"); 1057 } 1058 vfree(counters); 1059 xt_table_unlock(t); 1060 return ret; 1061 1062 put_module: 1063 module_put(t->me); 1064 xt_table_unlock(t); 1065 free_newinfo_counters_untrans: 1066 vfree(counters); 1067 out: 1068 return ret; 1069 } 1070 1071 static int do_replace(struct net *net, const void __user *user, 1072 unsigned int len) 1073 { 1074 int ret; 1075 struct arpt_replace tmp; 1076 struct xt_table_info *newinfo; 1077 void *loc_cpu_entry; 1078 struct arpt_entry *iter; 1079 1080 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1081 return -EFAULT; 1082 1083 /* overflow check */ 1084 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) 1085 return -ENOMEM; 1086 if (tmp.num_counters == 0) 1087 return -EINVAL; 1088 1089 tmp.name[sizeof(tmp.name)-1] = 0; 1090 1091 newinfo = xt_alloc_table_info(tmp.size); 1092 if (!newinfo) 1093 return -ENOMEM; 1094 1095 loc_cpu_entry = newinfo->entries; 1096 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), 1097 tmp.size) != 0) { 1098 ret = -EFAULT; 1099 goto free_newinfo; 1100 } 1101 1102 ret = translate_table(newinfo, loc_cpu_entry, &tmp); 1103 if (ret != 0) 1104 goto free_newinfo; 1105 1106 duprintf("arp_tables: Translated table\n"); 1107 1108 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, 1109 tmp.num_counters, tmp.counters); 1110 if (ret) 1111 goto free_newinfo_untrans; 1112 return 0; 1113 1114 free_newinfo_untrans: 1115 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) 1116 cleanup_entry(iter); 1117 free_newinfo: 1118 xt_free_table_info(newinfo); 1119 return ret; 1120 } 1121 1122 static int do_add_counters(struct net *net, const void __user *user, 1123 unsigned int len, int compat) 1124 { 1125 unsigned int i; 1126 struct xt_counters_info tmp; 1127 struct xt_counters *paddc; 1128 unsigned int num_counters; 1129 const char *name; 1130 int size; 1131 void *ptmp; 1132 struct xt_table *t; 1133 const struct xt_table_info *private; 1134 int ret = 0; 1135 struct arpt_entry *iter; 1136 unsigned int addend; 1137 #ifdef CONFIG_COMPAT 1138 struct compat_xt_counters_info compat_tmp; 1139 1140 if (compat) { 1141 ptmp = &compat_tmp; 1142 size = sizeof(struct compat_xt_counters_info); 1143 } else 1144 #endif 1145 { 1146 ptmp = &tmp; 1147 size = sizeof(struct xt_counters_info); 1148 } 1149 1150 if (copy_from_user(ptmp, user, size) != 0) 1151 return -EFAULT; 1152 1153 #ifdef CONFIG_COMPAT 1154 if (compat) { 1155 num_counters = compat_tmp.num_counters; 1156 name = compat_tmp.name; 1157 } else 1158 #endif 1159 { 1160 num_counters = tmp.num_counters; 1161 name = tmp.name; 1162 } 1163 1164 if (len != size + num_counters * sizeof(struct xt_counters)) 1165 return -EINVAL; 1166 1167 paddc = vmalloc(len - size); 1168 if (!paddc) 1169 return -ENOMEM; 1170 1171 if (copy_from_user(paddc, user + size, len - size) != 0) { 1172 ret = -EFAULT; 1173 goto free; 1174 } 1175 1176 t = xt_find_table_lock(net, NFPROTO_ARP, name); 1177 if (IS_ERR_OR_NULL(t)) { 1178 ret = t ? PTR_ERR(t) : -ENOENT; 1179 goto free; 1180 } 1181 1182 local_bh_disable(); 1183 private = t->private; 1184 if (private->number != num_counters) { 1185 ret = -EINVAL; 1186 goto unlock_up_free; 1187 } 1188 1189 i = 0; 1190 1191 addend = xt_write_recseq_begin(); 1192 xt_entry_foreach(iter, private->entries, private->size) { 1193 struct xt_counters *tmp; 1194 1195 tmp = xt_get_this_cpu_counter(&iter->counters); 1196 ADD_COUNTER(*tmp, paddc[i].bcnt, paddc[i].pcnt); 1197 ++i; 1198 } 1199 xt_write_recseq_end(addend); 1200 unlock_up_free: 1201 local_bh_enable(); 1202 xt_table_unlock(t); 1203 module_put(t->me); 1204 free: 1205 vfree(paddc); 1206 1207 return ret; 1208 } 1209 1210 #ifdef CONFIG_COMPAT 1211 static inline void compat_release_entry(struct compat_arpt_entry *e) 1212 { 1213 struct xt_entry_target *t; 1214 1215 t = compat_arpt_get_target(e); 1216 module_put(t->u.kernel.target->me); 1217 } 1218 1219 static inline int 1220 check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, 1221 struct xt_table_info *newinfo, 1222 unsigned int *size, 1223 const unsigned char *base, 1224 const unsigned char *limit, 1225 const unsigned int *hook_entries, 1226 const unsigned int *underflows, 1227 const char *name) 1228 { 1229 struct xt_entry_target *t; 1230 struct xt_target *target; 1231 unsigned int entry_offset; 1232 int ret, off, h; 1233 1234 duprintf("check_compat_entry_size_and_hooks %p\n", e); 1235 if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 || 1236 (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit) { 1237 duprintf("Bad offset %p, limit = %p\n", e, limit); 1238 return -EINVAL; 1239 } 1240 1241 if (e->next_offset < sizeof(struct compat_arpt_entry) + 1242 sizeof(struct compat_xt_entry_target)) { 1243 duprintf("checking: element %p size %u\n", 1244 e, e->next_offset); 1245 return -EINVAL; 1246 } 1247 1248 /* For purposes of check_entry casting the compat entry is fine */ 1249 ret = check_entry((struct arpt_entry *)e, name); 1250 if (ret) 1251 return ret; 1252 1253 off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); 1254 entry_offset = (void *)e - (void *)base; 1255 1256 t = compat_arpt_get_target(e); 1257 target = xt_request_find_target(NFPROTO_ARP, t->u.user.name, 1258 t->u.user.revision); 1259 if (IS_ERR(target)) { 1260 duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", 1261 t->u.user.name); 1262 ret = PTR_ERR(target); 1263 goto out; 1264 } 1265 t->u.kernel.target = target; 1266 1267 off += xt_compat_target_offset(target); 1268 *size += off; 1269 ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off); 1270 if (ret) 1271 goto release_target; 1272 1273 /* Check hooks & underflows */ 1274 for (h = 0; h < NF_ARP_NUMHOOKS; h++) { 1275 if ((unsigned char *)e - base == hook_entries[h]) 1276 newinfo->hook_entry[h] = hook_entries[h]; 1277 if ((unsigned char *)e - base == underflows[h]) 1278 newinfo->underflow[h] = underflows[h]; 1279 } 1280 1281 /* Clear counters and comefrom */ 1282 memset(&e->counters, 0, sizeof(e->counters)); 1283 e->comefrom = 0; 1284 return 0; 1285 1286 release_target: 1287 module_put(t->u.kernel.target->me); 1288 out: 1289 return ret; 1290 } 1291 1292 static int 1293 compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, 1294 unsigned int *size, const char *name, 1295 struct xt_table_info *newinfo, unsigned char *base) 1296 { 1297 struct xt_entry_target *t; 1298 struct xt_target *target; 1299 struct arpt_entry *de; 1300 unsigned int origsize; 1301 int ret, h; 1302 1303 ret = 0; 1304 origsize = *size; 1305 de = (struct arpt_entry *)*dstptr; 1306 memcpy(de, e, sizeof(struct arpt_entry)); 1307 memcpy(&de->counters, &e->counters, sizeof(e->counters)); 1308 1309 *dstptr += sizeof(struct arpt_entry); 1310 *size += sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); 1311 1312 de->target_offset = e->target_offset - (origsize - *size); 1313 t = compat_arpt_get_target(e); 1314 target = t->u.kernel.target; 1315 xt_compat_target_from_user(t, dstptr, size); 1316 1317 de->next_offset = e->next_offset - (origsize - *size); 1318 for (h = 0; h < NF_ARP_NUMHOOKS; h++) { 1319 if ((unsigned char *)de - base < newinfo->hook_entry[h]) 1320 newinfo->hook_entry[h] -= origsize - *size; 1321 if ((unsigned char *)de - base < newinfo->underflow[h]) 1322 newinfo->underflow[h] -= origsize - *size; 1323 } 1324 return ret; 1325 } 1326 1327 static int translate_compat_table(const char *name, 1328 unsigned int valid_hooks, 1329 struct xt_table_info **pinfo, 1330 void **pentry0, 1331 unsigned int total_size, 1332 unsigned int number, 1333 unsigned int *hook_entries, 1334 unsigned int *underflows) 1335 { 1336 unsigned int i, j; 1337 struct xt_table_info *newinfo, *info; 1338 void *pos, *entry0, *entry1; 1339 struct compat_arpt_entry *iter0; 1340 struct arpt_entry *iter1; 1341 unsigned int size; 1342 int ret = 0; 1343 1344 info = *pinfo; 1345 entry0 = *pentry0; 1346 size = total_size; 1347 info->number = number; 1348 1349 /* Init all hooks to impossible value. */ 1350 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 1351 info->hook_entry[i] = 0xFFFFFFFF; 1352 info->underflow[i] = 0xFFFFFFFF; 1353 } 1354 1355 duprintf("translate_compat_table: size %u\n", info->size); 1356 j = 0; 1357 xt_compat_lock(NFPROTO_ARP); 1358 xt_compat_init_offsets(NFPROTO_ARP, number); 1359 /* Walk through entries, checking offsets. */ 1360 xt_entry_foreach(iter0, entry0, total_size) { 1361 ret = check_compat_entry_size_and_hooks(iter0, info, &size, 1362 entry0, 1363 entry0 + total_size, 1364 hook_entries, 1365 underflows, 1366 name); 1367 if (ret != 0) 1368 goto out_unlock; 1369 ++j; 1370 } 1371 1372 ret = -EINVAL; 1373 if (j != number) { 1374 duprintf("translate_compat_table: %u not %u entries\n", 1375 j, number); 1376 goto out_unlock; 1377 } 1378 1379 /* Check hooks all assigned */ 1380 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 1381 /* Only hooks which are valid */ 1382 if (!(valid_hooks & (1 << i))) 1383 continue; 1384 if (info->hook_entry[i] == 0xFFFFFFFF) { 1385 duprintf("Invalid hook entry %u %u\n", 1386 i, hook_entries[i]); 1387 goto out_unlock; 1388 } 1389 if (info->underflow[i] == 0xFFFFFFFF) { 1390 duprintf("Invalid underflow %u %u\n", 1391 i, underflows[i]); 1392 goto out_unlock; 1393 } 1394 } 1395 1396 ret = -ENOMEM; 1397 newinfo = xt_alloc_table_info(size); 1398 if (!newinfo) 1399 goto out_unlock; 1400 1401 newinfo->number = number; 1402 for (i = 0; i < NF_ARP_NUMHOOKS; i++) { 1403 newinfo->hook_entry[i] = info->hook_entry[i]; 1404 newinfo->underflow[i] = info->underflow[i]; 1405 } 1406 entry1 = newinfo->entries; 1407 pos = entry1; 1408 size = total_size; 1409 xt_entry_foreach(iter0, entry0, total_size) { 1410 ret = compat_copy_entry_from_user(iter0, &pos, &size, 1411 name, newinfo, entry1); 1412 if (ret != 0) 1413 break; 1414 } 1415 xt_compat_flush_offsets(NFPROTO_ARP); 1416 xt_compat_unlock(NFPROTO_ARP); 1417 if (ret) 1418 goto free_newinfo; 1419 1420 ret = -ELOOP; 1421 if (!mark_source_chains(newinfo, valid_hooks, entry1)) 1422 goto free_newinfo; 1423 1424 i = 0; 1425 xt_entry_foreach(iter1, entry1, newinfo->size) { 1426 iter1->counters.pcnt = xt_percpu_counter_alloc(); 1427 if (IS_ERR_VALUE(iter1->counters.pcnt)) { 1428 ret = -ENOMEM; 1429 break; 1430 } 1431 1432 ret = check_target(iter1, name); 1433 if (ret != 0) { 1434 xt_percpu_counter_free(iter1->counters.pcnt); 1435 break; 1436 } 1437 ++i; 1438 if (strcmp(arpt_get_target(iter1)->u.user.name, 1439 XT_ERROR_TARGET) == 0) 1440 ++newinfo->stacksize; 1441 } 1442 if (ret) { 1443 /* 1444 * The first i matches need cleanup_entry (calls ->destroy) 1445 * because they had called ->check already. The other j-i 1446 * entries need only release. 1447 */ 1448 int skip = i; 1449 j -= i; 1450 xt_entry_foreach(iter0, entry0, newinfo->size) { 1451 if (skip-- > 0) 1452 continue; 1453 if (j-- == 0) 1454 break; 1455 compat_release_entry(iter0); 1456 } 1457 xt_entry_foreach(iter1, entry1, newinfo->size) { 1458 if (i-- == 0) 1459 break; 1460 cleanup_entry(iter1); 1461 } 1462 xt_free_table_info(newinfo); 1463 return ret; 1464 } 1465 1466 *pinfo = newinfo; 1467 *pentry0 = entry1; 1468 xt_free_table_info(info); 1469 return 0; 1470 1471 free_newinfo: 1472 xt_free_table_info(newinfo); 1473 out: 1474 xt_entry_foreach(iter0, entry0, total_size) { 1475 if (j-- == 0) 1476 break; 1477 compat_release_entry(iter0); 1478 } 1479 return ret; 1480 out_unlock: 1481 xt_compat_flush_offsets(NFPROTO_ARP); 1482 xt_compat_unlock(NFPROTO_ARP); 1483 goto out; 1484 } 1485 1486 struct compat_arpt_replace { 1487 char name[XT_TABLE_MAXNAMELEN]; 1488 u32 valid_hooks; 1489 u32 num_entries; 1490 u32 size; 1491 u32 hook_entry[NF_ARP_NUMHOOKS]; 1492 u32 underflow[NF_ARP_NUMHOOKS]; 1493 u32 num_counters; 1494 compat_uptr_t counters; 1495 struct compat_arpt_entry entries[0]; 1496 }; 1497 1498 static int compat_do_replace(struct net *net, void __user *user, 1499 unsigned int len) 1500 { 1501 int ret; 1502 struct compat_arpt_replace tmp; 1503 struct xt_table_info *newinfo; 1504 void *loc_cpu_entry; 1505 struct arpt_entry *iter; 1506 1507 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1508 return -EFAULT; 1509 1510 /* overflow check */ 1511 if (tmp.size >= INT_MAX / num_possible_cpus()) 1512 return -ENOMEM; 1513 if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters)) 1514 return -ENOMEM; 1515 if (tmp.num_counters == 0) 1516 return -EINVAL; 1517 1518 tmp.name[sizeof(tmp.name)-1] = 0; 1519 1520 newinfo = xt_alloc_table_info(tmp.size); 1521 if (!newinfo) 1522 return -ENOMEM; 1523 1524 loc_cpu_entry = newinfo->entries; 1525 if (copy_from_user(loc_cpu_entry, user + sizeof(tmp), tmp.size) != 0) { 1526 ret = -EFAULT; 1527 goto free_newinfo; 1528 } 1529 1530 ret = translate_compat_table(tmp.name, tmp.valid_hooks, 1531 &newinfo, &loc_cpu_entry, tmp.size, 1532 tmp.num_entries, tmp.hook_entry, 1533 tmp.underflow); 1534 if (ret != 0) 1535 goto free_newinfo; 1536 1537 duprintf("compat_do_replace: Translated table\n"); 1538 1539 ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo, 1540 tmp.num_counters, compat_ptr(tmp.counters)); 1541 if (ret) 1542 goto free_newinfo_untrans; 1543 return 0; 1544 1545 free_newinfo_untrans: 1546 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) 1547 cleanup_entry(iter); 1548 free_newinfo: 1549 xt_free_table_info(newinfo); 1550 return ret; 1551 } 1552 1553 static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, 1554 unsigned int len) 1555 { 1556 int ret; 1557 1558 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) 1559 return -EPERM; 1560 1561 switch (cmd) { 1562 case ARPT_SO_SET_REPLACE: 1563 ret = compat_do_replace(sock_net(sk), user, len); 1564 break; 1565 1566 case ARPT_SO_SET_ADD_COUNTERS: 1567 ret = do_add_counters(sock_net(sk), user, len, 1); 1568 break; 1569 1570 default: 1571 duprintf("do_arpt_set_ctl: unknown request %i\n", cmd); 1572 ret = -EINVAL; 1573 } 1574 1575 return ret; 1576 } 1577 1578 static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, 1579 compat_uint_t *size, 1580 struct xt_counters *counters, 1581 unsigned int i) 1582 { 1583 struct xt_entry_target *t; 1584 struct compat_arpt_entry __user *ce; 1585 u_int16_t target_offset, next_offset; 1586 compat_uint_t origsize; 1587 int ret; 1588 1589 origsize = *size; 1590 ce = (struct compat_arpt_entry __user *)*dstptr; 1591 if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 || 1592 copy_to_user(&ce->counters, &counters[i], 1593 sizeof(counters[i])) != 0) 1594 return -EFAULT; 1595 1596 *dstptr += sizeof(struct compat_arpt_entry); 1597 *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); 1598 1599 target_offset = e->target_offset - (origsize - *size); 1600 1601 t = arpt_get_target(e); 1602 ret = xt_compat_target_to_user(t, dstptr, size); 1603 if (ret) 1604 return ret; 1605 next_offset = e->next_offset - (origsize - *size); 1606 if (put_user(target_offset, &ce->target_offset) != 0 || 1607 put_user(next_offset, &ce->next_offset) != 0) 1608 return -EFAULT; 1609 return 0; 1610 } 1611 1612 static int compat_copy_entries_to_user(unsigned int total_size, 1613 struct xt_table *table, 1614 void __user *userptr) 1615 { 1616 struct xt_counters *counters; 1617 const struct xt_table_info *private = table->private; 1618 void __user *pos; 1619 unsigned int size; 1620 int ret = 0; 1621 unsigned int i = 0; 1622 struct arpt_entry *iter; 1623 1624 counters = alloc_counters(table); 1625 if (IS_ERR(counters)) 1626 return PTR_ERR(counters); 1627 1628 pos = userptr; 1629 size = total_size; 1630 xt_entry_foreach(iter, private->entries, total_size) { 1631 ret = compat_copy_entry_to_user(iter, &pos, 1632 &size, counters, i++); 1633 if (ret != 0) 1634 break; 1635 } 1636 vfree(counters); 1637 return ret; 1638 } 1639 1640 struct compat_arpt_get_entries { 1641 char name[XT_TABLE_MAXNAMELEN]; 1642 compat_uint_t size; 1643 struct compat_arpt_entry entrytable[0]; 1644 }; 1645 1646 static int compat_get_entries(struct net *net, 1647 struct compat_arpt_get_entries __user *uptr, 1648 int *len) 1649 { 1650 int ret; 1651 struct compat_arpt_get_entries get; 1652 struct xt_table *t; 1653 1654 if (*len < sizeof(get)) { 1655 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get)); 1656 return -EINVAL; 1657 } 1658 if (copy_from_user(&get, uptr, sizeof(get)) != 0) 1659 return -EFAULT; 1660 if (*len != sizeof(struct compat_arpt_get_entries) + get.size) { 1661 duprintf("compat_get_entries: %u != %zu\n", 1662 *len, sizeof(get) + get.size); 1663 return -EINVAL; 1664 } 1665 1666 xt_compat_lock(NFPROTO_ARP); 1667 t = xt_find_table_lock(net, NFPROTO_ARP, get.name); 1668 if (!IS_ERR_OR_NULL(t)) { 1669 const struct xt_table_info *private = t->private; 1670 struct xt_table_info info; 1671 1672 duprintf("t->private->number = %u\n", private->number); 1673 ret = compat_table_info(private, &info); 1674 if (!ret && get.size == info.size) { 1675 ret = compat_copy_entries_to_user(private->size, 1676 t, uptr->entrytable); 1677 } else if (!ret) { 1678 duprintf("compat_get_entries: I've got %u not %u!\n", 1679 private->size, get.size); 1680 ret = -EAGAIN; 1681 } 1682 xt_compat_flush_offsets(NFPROTO_ARP); 1683 module_put(t->me); 1684 xt_table_unlock(t); 1685 } else 1686 ret = t ? PTR_ERR(t) : -ENOENT; 1687 1688 xt_compat_unlock(NFPROTO_ARP); 1689 return ret; 1690 } 1691 1692 static int do_arpt_get_ctl(struct sock *, int, void __user *, int *); 1693 1694 static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, 1695 int *len) 1696 { 1697 int ret; 1698 1699 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) 1700 return -EPERM; 1701 1702 switch (cmd) { 1703 case ARPT_SO_GET_INFO: 1704 ret = get_info(sock_net(sk), user, len, 1); 1705 break; 1706 case ARPT_SO_GET_ENTRIES: 1707 ret = compat_get_entries(sock_net(sk), user, len); 1708 break; 1709 default: 1710 ret = do_arpt_get_ctl(sk, cmd, user, len); 1711 } 1712 return ret; 1713 } 1714 #endif 1715 1716 static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) 1717 { 1718 int ret; 1719 1720 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) 1721 return -EPERM; 1722 1723 switch (cmd) { 1724 case ARPT_SO_SET_REPLACE: 1725 ret = do_replace(sock_net(sk), user, len); 1726 break; 1727 1728 case ARPT_SO_SET_ADD_COUNTERS: 1729 ret = do_add_counters(sock_net(sk), user, len, 0); 1730 break; 1731 1732 default: 1733 duprintf("do_arpt_set_ctl: unknown request %i\n", cmd); 1734 ret = -EINVAL; 1735 } 1736 1737 return ret; 1738 } 1739 1740 static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) 1741 { 1742 int ret; 1743 1744 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) 1745 return -EPERM; 1746 1747 switch (cmd) { 1748 case ARPT_SO_GET_INFO: 1749 ret = get_info(sock_net(sk), user, len, 0); 1750 break; 1751 1752 case ARPT_SO_GET_ENTRIES: 1753 ret = get_entries(sock_net(sk), user, len); 1754 break; 1755 1756 case ARPT_SO_GET_REVISION_TARGET: { 1757 struct xt_get_revision rev; 1758 1759 if (*len != sizeof(rev)) { 1760 ret = -EINVAL; 1761 break; 1762 } 1763 if (copy_from_user(&rev, user, sizeof(rev)) != 0) { 1764 ret = -EFAULT; 1765 break; 1766 } 1767 rev.name[sizeof(rev.name)-1] = 0; 1768 1769 try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name, 1770 rev.revision, 1, &ret), 1771 "arpt_%s", rev.name); 1772 break; 1773 } 1774 1775 default: 1776 duprintf("do_arpt_get_ctl: unknown request %i\n", cmd); 1777 ret = -EINVAL; 1778 } 1779 1780 return ret; 1781 } 1782 1783 struct xt_table *arpt_register_table(struct net *net, 1784 const struct xt_table *table, 1785 const struct arpt_replace *repl) 1786 { 1787 int ret; 1788 struct xt_table_info *newinfo; 1789 struct xt_table_info bootstrap = {0}; 1790 void *loc_cpu_entry; 1791 struct xt_table *new_table; 1792 1793 newinfo = xt_alloc_table_info(repl->size); 1794 if (!newinfo) { 1795 ret = -ENOMEM; 1796 goto out; 1797 } 1798 1799 loc_cpu_entry = newinfo->entries; 1800 memcpy(loc_cpu_entry, repl->entries, repl->size); 1801 1802 ret = translate_table(newinfo, loc_cpu_entry, repl); 1803 duprintf("arpt_register_table: translate table gives %d\n", ret); 1804 if (ret != 0) 1805 goto out_free; 1806 1807 new_table = xt_register_table(net, table, &bootstrap, newinfo); 1808 if (IS_ERR(new_table)) { 1809 ret = PTR_ERR(new_table); 1810 goto out_free; 1811 } 1812 return new_table; 1813 1814 out_free: 1815 xt_free_table_info(newinfo); 1816 out: 1817 return ERR_PTR(ret); 1818 } 1819 1820 void arpt_unregister_table(struct xt_table *table) 1821 { 1822 struct xt_table_info *private; 1823 void *loc_cpu_entry; 1824 struct module *table_owner = table->me; 1825 struct arpt_entry *iter; 1826 1827 private = xt_unregister_table(table); 1828 1829 /* Decrease module usage counts and free resources */ 1830 loc_cpu_entry = private->entries; 1831 xt_entry_foreach(iter, loc_cpu_entry, private->size) 1832 cleanup_entry(iter); 1833 if (private->number > private->initial_entries) 1834 module_put(table_owner); 1835 xt_free_table_info(private); 1836 } 1837 1838 /* The built-in targets: standard (NULL) and error. */ 1839 static struct xt_target arpt_builtin_tg[] __read_mostly = { 1840 { 1841 .name = XT_STANDARD_TARGET, 1842 .targetsize = sizeof(int), 1843 .family = NFPROTO_ARP, 1844 #ifdef CONFIG_COMPAT 1845 .compatsize = sizeof(compat_int_t), 1846 .compat_from_user = compat_standard_from_user, 1847 .compat_to_user = compat_standard_to_user, 1848 #endif 1849 }, 1850 { 1851 .name = XT_ERROR_TARGET, 1852 .target = arpt_error, 1853 .targetsize = XT_FUNCTION_MAXNAMELEN, 1854 .family = NFPROTO_ARP, 1855 }, 1856 }; 1857 1858 static struct nf_sockopt_ops arpt_sockopts = { 1859 .pf = PF_INET, 1860 .set_optmin = ARPT_BASE_CTL, 1861 .set_optmax = ARPT_SO_SET_MAX+1, 1862 .set = do_arpt_set_ctl, 1863 #ifdef CONFIG_COMPAT 1864 .compat_set = compat_do_arpt_set_ctl, 1865 #endif 1866 .get_optmin = ARPT_BASE_CTL, 1867 .get_optmax = ARPT_SO_GET_MAX+1, 1868 .get = do_arpt_get_ctl, 1869 #ifdef CONFIG_COMPAT 1870 .compat_get = compat_do_arpt_get_ctl, 1871 #endif 1872 .owner = THIS_MODULE, 1873 }; 1874 1875 static int __net_init arp_tables_net_init(struct net *net) 1876 { 1877 return xt_proto_init(net, NFPROTO_ARP); 1878 } 1879 1880 static void __net_exit arp_tables_net_exit(struct net *net) 1881 { 1882 xt_proto_fini(net, NFPROTO_ARP); 1883 } 1884 1885 static struct pernet_operations arp_tables_net_ops = { 1886 .init = arp_tables_net_init, 1887 .exit = arp_tables_net_exit, 1888 }; 1889 1890 static int __init arp_tables_init(void) 1891 { 1892 int ret; 1893 1894 ret = register_pernet_subsys(&arp_tables_net_ops); 1895 if (ret < 0) 1896 goto err1; 1897 1898 /* No one else will be downing sem now, so we won't sleep */ 1899 ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); 1900 if (ret < 0) 1901 goto err2; 1902 1903 /* Register setsockopt */ 1904 ret = nf_register_sockopt(&arpt_sockopts); 1905 if (ret < 0) 1906 goto err4; 1907 1908 printk(KERN_INFO "arp_tables: (C) 2002 David S. Miller\n"); 1909 return 0; 1910 1911 err4: 1912 xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); 1913 err2: 1914 unregister_pernet_subsys(&arp_tables_net_ops); 1915 err1: 1916 return ret; 1917 } 1918 1919 static void __exit arp_tables_fini(void) 1920 { 1921 nf_unregister_sockopt(&arpt_sockopts); 1922 xt_unregister_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); 1923 unregister_pernet_subsys(&arp_tables_net_ops); 1924 } 1925 1926 EXPORT_SYMBOL(arpt_register_table); 1927 EXPORT_SYMBOL(arpt_unregister_table); 1928 EXPORT_SYMBOL(arpt_do_table); 1929 1930 module_init(arp_tables_init); 1931 module_exit(arp_tables_fini); 1932