1 /* Helper handling for netfilter. */ 2 3 /* (C) 1999-2001 Paul `Rusty' Russell 4 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> 5 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> 6 * (C) 2006-2012 Patrick McHardy <kaber@trash.net> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/types.h> 14 #include <linux/netfilter.h> 15 #include <linux/module.h> 16 #include <linux/skbuff.h> 17 #include <linux/vmalloc.h> 18 #include <linux/stddef.h> 19 #include <linux/random.h> 20 #include <linux/err.h> 21 #include <linux/kernel.h> 22 #include <linux/netdevice.h> 23 #include <linux/rculist.h> 24 #include <linux/rtnetlink.h> 25 26 #include <net/netfilter/nf_conntrack.h> 27 #include <net/netfilter/nf_conntrack_l3proto.h> 28 #include <net/netfilter/nf_conntrack_l4proto.h> 29 #include <net/netfilter/nf_conntrack_helper.h> 30 #include <net/netfilter/nf_conntrack_core.h> 31 #include <net/netfilter/nf_conntrack_extend.h> 32 #include <net/netfilter/nf_log.h> 33 34 static DEFINE_MUTEX(nf_ct_helper_mutex); 35 struct hlist_head *nf_ct_helper_hash __read_mostly; 36 EXPORT_SYMBOL_GPL(nf_ct_helper_hash); 37 unsigned int nf_ct_helper_hsize __read_mostly; 38 EXPORT_SYMBOL_GPL(nf_ct_helper_hsize); 39 static unsigned int nf_ct_helper_count __read_mostly; 40 41 static bool nf_ct_auto_assign_helper __read_mostly = false; 42 module_param_named(nf_conntrack_helper, nf_ct_auto_assign_helper, bool, 0644); 43 MODULE_PARM_DESC(nf_conntrack_helper, 44 "Enable automatic conntrack helper assignment (default 0)"); 45 46 #ifdef CONFIG_SYSCTL 47 static struct ctl_table helper_sysctl_table[] = { 48 { 49 .procname = "nf_conntrack_helper", 50 .data = &init_net.ct.sysctl_auto_assign_helper, 51 .maxlen = sizeof(unsigned int), 52 .mode = 0644, 53 .proc_handler = proc_dointvec, 54 }, 55 {} 56 }; 57 58 static int nf_conntrack_helper_init_sysctl(struct net *net) 59 { 60 struct ctl_table *table; 61 62 table = kmemdup(helper_sysctl_table, sizeof(helper_sysctl_table), 63 GFP_KERNEL); 64 if (!table) 65 goto out; 66 67 table[0].data = &net->ct.sysctl_auto_assign_helper; 68 69 /* Don't export sysctls to unprivileged users */ 70 if (net->user_ns != &init_user_ns) 71 table[0].procname = NULL; 72 73 net->ct.helper_sysctl_header = 74 register_net_sysctl(net, "net/netfilter", table); 75 76 if (!net->ct.helper_sysctl_header) { 77 pr_err("nf_conntrack_helper: can't register to sysctl.\n"); 78 goto out_register; 79 } 80 return 0; 81 82 out_register: 83 kfree(table); 84 out: 85 return -ENOMEM; 86 } 87 88 static void nf_conntrack_helper_fini_sysctl(struct net *net) 89 { 90 struct ctl_table *table; 91 92 table = net->ct.helper_sysctl_header->ctl_table_arg; 93 unregister_net_sysctl_table(net->ct.helper_sysctl_header); 94 kfree(table); 95 } 96 #else 97 static int nf_conntrack_helper_init_sysctl(struct net *net) 98 { 99 return 0; 100 } 101 102 static void nf_conntrack_helper_fini_sysctl(struct net *net) 103 { 104 } 105 #endif /* CONFIG_SYSCTL */ 106 107 /* Stupid hash, but collision free for the default registrations of the 108 * helpers currently in the kernel. */ 109 static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple) 110 { 111 return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^ 112 (__force __u16)tuple->src.u.all) % nf_ct_helper_hsize; 113 } 114 115 static struct nf_conntrack_helper * 116 __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) 117 { 118 struct nf_conntrack_helper *helper; 119 struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; 120 unsigned int h; 121 122 if (!nf_ct_helper_count) 123 return NULL; 124 125 h = helper_hash(tuple); 126 hlist_for_each_entry_rcu(helper, &nf_ct_helper_hash[h], hnode) { 127 if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask)) 128 return helper; 129 } 130 return NULL; 131 } 132 133 struct nf_conntrack_helper * 134 __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum) 135 { 136 struct nf_conntrack_helper *h; 137 unsigned int i; 138 139 for (i = 0; i < nf_ct_helper_hsize; i++) { 140 hlist_for_each_entry_rcu(h, &nf_ct_helper_hash[i], hnode) { 141 if (strcmp(h->name, name)) 142 continue; 143 144 if (h->tuple.src.l3num != NFPROTO_UNSPEC && 145 h->tuple.src.l3num != l3num) 146 continue; 147 148 if (h->tuple.dst.protonum == protonum) 149 return h; 150 } 151 } 152 return NULL; 153 } 154 EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find); 155 156 struct nf_conntrack_helper * 157 nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum) 158 { 159 struct nf_conntrack_helper *h; 160 161 h = __nf_conntrack_helper_find(name, l3num, protonum); 162 #ifdef CONFIG_MODULES 163 if (h == NULL) { 164 if (request_module("nfct-helper-%s", name) == 0) 165 h = __nf_conntrack_helper_find(name, l3num, protonum); 166 } 167 #endif 168 if (h != NULL && !try_module_get(h->me)) 169 h = NULL; 170 171 return h; 172 } 173 EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get); 174 175 struct nf_conn_help * 176 nf_ct_helper_ext_add(struct nf_conn *ct, 177 struct nf_conntrack_helper *helper, gfp_t gfp) 178 { 179 struct nf_conn_help *help; 180 181 help = nf_ct_ext_add_length(ct, NF_CT_EXT_HELPER, 182 helper->data_len, gfp); 183 if (help) 184 INIT_HLIST_HEAD(&help->expectations); 185 else 186 pr_debug("failed to add helper extension area"); 187 return help; 188 } 189 EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); 190 191 static struct nf_conntrack_helper * 192 nf_ct_lookup_helper(struct nf_conn *ct, struct net *net) 193 { 194 if (!net->ct.sysctl_auto_assign_helper) { 195 if (net->ct.auto_assign_helper_warned) 196 return NULL; 197 if (!__nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple)) 198 return NULL; 199 pr_info("nf_conntrack: default automatic helper assignment " 200 "has been turned off for security reasons and CT-based " 201 " firewall rule not found. Use the iptables CT target " 202 "to attach helpers instead.\n"); 203 net->ct.auto_assign_helper_warned = 1; 204 return NULL; 205 } 206 207 return __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); 208 } 209 210 211 int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, 212 gfp_t flags) 213 { 214 struct nf_conntrack_helper *helper = NULL; 215 struct nf_conn_help *help; 216 struct net *net = nf_ct_net(ct); 217 218 /* We already got a helper explicitly attached. The function 219 * nf_conntrack_alter_reply - in case NAT is in use - asks for looking 220 * the helper up again. Since now the user is in full control of 221 * making consistent helper configurations, skip this automatic 222 * re-lookup, otherwise we'll lose the helper. 223 */ 224 if (test_bit(IPS_HELPER_BIT, &ct->status)) 225 return 0; 226 227 if (tmpl != NULL) { 228 help = nfct_help(tmpl); 229 if (help != NULL) { 230 helper = help->helper; 231 set_bit(IPS_HELPER_BIT, &ct->status); 232 } 233 } 234 235 help = nfct_help(ct); 236 237 if (helper == NULL) { 238 helper = nf_ct_lookup_helper(ct, net); 239 if (helper == NULL) { 240 if (help) 241 RCU_INIT_POINTER(help->helper, NULL); 242 return 0; 243 } 244 } 245 246 if (help == NULL) { 247 help = nf_ct_helper_ext_add(ct, helper, flags); 248 if (help == NULL) 249 return -ENOMEM; 250 } else { 251 /* We only allow helper re-assignment of the same sort since 252 * we cannot reallocate the helper extension area. 253 */ 254 struct nf_conntrack_helper *tmp = rcu_dereference(help->helper); 255 256 if (tmp && tmp->help != helper->help) { 257 RCU_INIT_POINTER(help->helper, NULL); 258 return 0; 259 } 260 } 261 262 rcu_assign_pointer(help->helper, helper); 263 264 return 0; 265 } 266 EXPORT_SYMBOL_GPL(__nf_ct_try_assign_helper); 267 268 /* appropriate ct lock protecting must be taken by caller */ 269 static inline int unhelp(struct nf_conntrack_tuple_hash *i, 270 const struct nf_conntrack_helper *me) 271 { 272 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); 273 struct nf_conn_help *help = nfct_help(ct); 274 275 if (help && rcu_dereference_raw(help->helper) == me) { 276 nf_conntrack_event(IPCT_HELPER, ct); 277 RCU_INIT_POINTER(help->helper, NULL); 278 } 279 return 0; 280 } 281 282 void nf_ct_helper_destroy(struct nf_conn *ct) 283 { 284 struct nf_conn_help *help = nfct_help(ct); 285 struct nf_conntrack_helper *helper; 286 287 if (help) { 288 rcu_read_lock(); 289 helper = rcu_dereference(help->helper); 290 if (helper && helper->destroy) 291 helper->destroy(ct); 292 rcu_read_unlock(); 293 } 294 } 295 296 static LIST_HEAD(nf_ct_helper_expectfn_list); 297 298 void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n) 299 { 300 spin_lock_bh(&nf_conntrack_expect_lock); 301 list_add_rcu(&n->head, &nf_ct_helper_expectfn_list); 302 spin_unlock_bh(&nf_conntrack_expect_lock); 303 } 304 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register); 305 306 void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n) 307 { 308 spin_lock_bh(&nf_conntrack_expect_lock); 309 list_del_rcu(&n->head); 310 spin_unlock_bh(&nf_conntrack_expect_lock); 311 } 312 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister); 313 314 struct nf_ct_helper_expectfn * 315 nf_ct_helper_expectfn_find_by_name(const char *name) 316 { 317 struct nf_ct_helper_expectfn *cur; 318 bool found = false; 319 320 rcu_read_lock(); 321 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { 322 if (!strcmp(cur->name, name)) { 323 found = true; 324 break; 325 } 326 } 327 rcu_read_unlock(); 328 return found ? cur : NULL; 329 } 330 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name); 331 332 struct nf_ct_helper_expectfn * 333 nf_ct_helper_expectfn_find_by_symbol(const void *symbol) 334 { 335 struct nf_ct_helper_expectfn *cur; 336 bool found = false; 337 338 rcu_read_lock(); 339 list_for_each_entry_rcu(cur, &nf_ct_helper_expectfn_list, head) { 340 if (cur->expectfn == symbol) { 341 found = true; 342 break; 343 } 344 } 345 rcu_read_unlock(); 346 return found ? cur : NULL; 347 } 348 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol); 349 350 __printf(3, 4) 351 void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct, 352 const char *fmt, ...) 353 { 354 const struct nf_conn_help *help; 355 const struct nf_conntrack_helper *helper; 356 struct va_format vaf; 357 va_list args; 358 359 va_start(args, fmt); 360 361 vaf.fmt = fmt; 362 vaf.va = &args; 363 364 /* Called from the helper function, this call never fails */ 365 help = nfct_help(ct); 366 367 /* rcu_read_lock()ed by nf_hook_thresh */ 368 helper = rcu_dereference(help->helper); 369 370 nf_log_packet(nf_ct_net(ct), nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, 371 "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf); 372 373 va_end(args); 374 } 375 EXPORT_SYMBOL_GPL(nf_ct_helper_log); 376 377 int nf_conntrack_helper_register(struct nf_conntrack_helper *me) 378 { 379 struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) }; 380 unsigned int h = helper_hash(&me->tuple); 381 struct nf_conntrack_helper *cur; 382 int ret = 0; 383 384 BUG_ON(me->expect_policy == NULL); 385 BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES); 386 BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1); 387 388 mutex_lock(&nf_ct_helper_mutex); 389 hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) { 390 if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple, &mask)) { 391 ret = -EEXIST; 392 goto out; 393 } 394 } 395 hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); 396 nf_ct_helper_count++; 397 out: 398 mutex_unlock(&nf_ct_helper_mutex); 399 return ret; 400 } 401 EXPORT_SYMBOL_GPL(nf_conntrack_helper_register); 402 403 static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, 404 struct net *net) 405 { 406 struct nf_conntrack_tuple_hash *h; 407 const struct hlist_nulls_node *nn; 408 int cpu; 409 410 /* Get rid of expecteds, set helpers to NULL. */ 411 for_each_possible_cpu(cpu) { 412 struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); 413 414 spin_lock_bh(&pcpu->lock); 415 hlist_nulls_for_each_entry(h, nn, &pcpu->unconfirmed, hnnode) 416 unhelp(h, me); 417 spin_unlock_bh(&pcpu->lock); 418 } 419 } 420 421 void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) 422 { 423 struct nf_conntrack_tuple_hash *h; 424 struct nf_conntrack_expect *exp; 425 const struct hlist_node *next; 426 const struct hlist_nulls_node *nn; 427 unsigned int last_hsize; 428 spinlock_t *lock; 429 struct net *net; 430 unsigned int i; 431 432 mutex_lock(&nf_ct_helper_mutex); 433 hlist_del_rcu(&me->hnode); 434 nf_ct_helper_count--; 435 mutex_unlock(&nf_ct_helper_mutex); 436 437 /* Make sure every nothing is still using the helper unless its a 438 * connection in the hash. 439 */ 440 synchronize_rcu(); 441 442 /* Get rid of expectations */ 443 spin_lock_bh(&nf_conntrack_expect_lock); 444 for (i = 0; i < nf_ct_expect_hsize; i++) { 445 hlist_for_each_entry_safe(exp, next, 446 &nf_ct_expect_hash[i], hnode) { 447 struct nf_conn_help *help = nfct_help(exp->master); 448 if ((rcu_dereference_protected( 449 help->helper, 450 lockdep_is_held(&nf_conntrack_expect_lock) 451 ) == me || exp->helper == me) && 452 del_timer(&exp->timeout)) { 453 nf_ct_unlink_expect(exp); 454 nf_ct_expect_put(exp); 455 } 456 } 457 } 458 spin_unlock_bh(&nf_conntrack_expect_lock); 459 460 rtnl_lock(); 461 for_each_net(net) 462 __nf_conntrack_helper_unregister(me, net); 463 rtnl_unlock(); 464 465 local_bh_disable(); 466 restart: 467 last_hsize = nf_conntrack_htable_size; 468 for (i = 0; i < last_hsize; i++) { 469 lock = &nf_conntrack_locks[i % CONNTRACK_LOCKS]; 470 nf_conntrack_lock(lock); 471 if (last_hsize != nf_conntrack_htable_size) { 472 spin_unlock(lock); 473 goto restart; 474 } 475 hlist_nulls_for_each_entry(h, nn, &nf_conntrack_hash[i], hnnode) 476 unhelp(h, me); 477 spin_unlock(lock); 478 } 479 local_bh_enable(); 480 } 481 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); 482 483 void nf_ct_helper_init(struct nf_conntrack_helper *helper, 484 u16 l3num, u16 protonum, const char *name, 485 u16 default_port, u16 spec_port, u32 id, 486 const struct nf_conntrack_expect_policy *exp_pol, 487 u32 expect_class_max, u32 data_len, 488 int (*help)(struct sk_buff *skb, unsigned int protoff, 489 struct nf_conn *ct, 490 enum ip_conntrack_info ctinfo), 491 int (*from_nlattr)(struct nlattr *attr, 492 struct nf_conn *ct), 493 struct module *module) 494 { 495 helper->tuple.src.l3num = l3num; 496 helper->tuple.dst.protonum = protonum; 497 helper->tuple.src.u.all = htons(spec_port); 498 helper->expect_policy = exp_pol; 499 helper->expect_class_max = expect_class_max; 500 helper->data_len = data_len; 501 helper->help = help; 502 helper->from_nlattr = from_nlattr; 503 helper->me = module; 504 505 if (spec_port == default_port) 506 snprintf(helper->name, sizeof(helper->name), "%s", name); 507 else 508 snprintf(helper->name, sizeof(helper->name), "%s-%u", name, id); 509 } 510 EXPORT_SYMBOL_GPL(nf_ct_helper_init); 511 512 int nf_conntrack_helpers_register(struct nf_conntrack_helper *helper, 513 unsigned int n) 514 { 515 unsigned int i; 516 int err = 0; 517 518 for (i = 0; i < n; i++) { 519 err = nf_conntrack_helper_register(&helper[i]); 520 if (err < 0) 521 goto err; 522 } 523 524 return err; 525 err: 526 if (i > 0) 527 nf_conntrack_helpers_unregister(helper, i); 528 return err; 529 } 530 EXPORT_SYMBOL_GPL(nf_conntrack_helpers_register); 531 532 void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *helper, 533 unsigned int n) 534 { 535 while (n-- > 0) 536 nf_conntrack_helper_unregister(&helper[n]); 537 } 538 EXPORT_SYMBOL_GPL(nf_conntrack_helpers_unregister); 539 540 static struct nf_ct_ext_type helper_extend __read_mostly = { 541 .len = sizeof(struct nf_conn_help), 542 .align = __alignof__(struct nf_conn_help), 543 .id = NF_CT_EXT_HELPER, 544 }; 545 546 int nf_conntrack_helper_pernet_init(struct net *net) 547 { 548 net->ct.auto_assign_helper_warned = false; 549 net->ct.sysctl_auto_assign_helper = nf_ct_auto_assign_helper; 550 return nf_conntrack_helper_init_sysctl(net); 551 } 552 553 void nf_conntrack_helper_pernet_fini(struct net *net) 554 { 555 nf_conntrack_helper_fini_sysctl(net); 556 } 557 558 int nf_conntrack_helper_init(void) 559 { 560 int ret; 561 nf_ct_helper_hsize = 1; /* gets rounded up to use one page */ 562 nf_ct_helper_hash = 563 nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0); 564 if (!nf_ct_helper_hash) 565 return -ENOMEM; 566 567 ret = nf_ct_extend_register(&helper_extend); 568 if (ret < 0) { 569 pr_err("nf_ct_helper: Unable to register helper extension.\n"); 570 goto out_extend; 571 } 572 573 return 0; 574 out_extend: 575 nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); 576 return ret; 577 } 578 579 void nf_conntrack_helper_fini(void) 580 { 581 nf_ct_extend_unregister(&helper_extend); 582 nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize); 583 } 584