| .. | .. |
|---|
| 33 | 33 | MODULE_LICENSE("GPL"); |
|---|
| 34 | 34 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
|---|
| 35 | 35 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); |
|---|
| 36 | +MODULE_DESCRIPTION("Netfilter messages via netlink socket"); |
|---|
| 36 | 37 | |
|---|
| 37 | 38 | #define nfnl_dereference_protected(id) \ |
|---|
| 38 | 39 | rcu_dereference_protected(table[(id)].subsys, \ |
|---|
| .. | .. |
|---|
| 44 | 45 | struct mutex mutex; |
|---|
| 45 | 46 | const struct nfnetlink_subsystem __rcu *subsys; |
|---|
| 46 | 47 | } table[NFNL_SUBSYS_COUNT]; |
|---|
| 48 | + |
|---|
| 49 | +static struct lock_class_key nfnl_lockdep_keys[NFNL_SUBSYS_COUNT]; |
|---|
| 50 | + |
|---|
| 51 | +static const char *const nfnl_lockdep_names[NFNL_SUBSYS_COUNT] = { |
|---|
| 52 | + [NFNL_SUBSYS_NONE] = "nfnl_subsys_none", |
|---|
| 53 | + [NFNL_SUBSYS_CTNETLINK] = "nfnl_subsys_ctnetlink", |
|---|
| 54 | + [NFNL_SUBSYS_CTNETLINK_EXP] = "nfnl_subsys_ctnetlink_exp", |
|---|
| 55 | + [NFNL_SUBSYS_QUEUE] = "nfnl_subsys_queue", |
|---|
| 56 | + [NFNL_SUBSYS_ULOG] = "nfnl_subsys_ulog", |
|---|
| 57 | + [NFNL_SUBSYS_OSF] = "nfnl_subsys_osf", |
|---|
| 58 | + [NFNL_SUBSYS_IPSET] = "nfnl_subsys_ipset", |
|---|
| 59 | + [NFNL_SUBSYS_ACCT] = "nfnl_subsys_acct", |
|---|
| 60 | + [NFNL_SUBSYS_CTNETLINK_TIMEOUT] = "nfnl_subsys_cttimeout", |
|---|
| 61 | + [NFNL_SUBSYS_CTHELPER] = "nfnl_subsys_cthelper", |
|---|
| 62 | + [NFNL_SUBSYS_NFTABLES] = "nfnl_subsys_nftables", |
|---|
| 63 | + [NFNL_SUBSYS_NFT_COMPAT] = "nfnl_subsys_nftcompat", |
|---|
| 64 | +}; |
|---|
| 47 | 65 | |
|---|
| 48 | 66 | static const int nfnl_group2type[NFNLGRP_MAX+1] = { |
|---|
| 49 | 67 | [NFNLGRP_CONNTRACK_NEW] = NFNL_SUBSYS_CTNETLINK, |
|---|
| .. | .. |
|---|
| 211 | 229 | return -ENOMEM; |
|---|
| 212 | 230 | } |
|---|
| 213 | 231 | |
|---|
| 214 | | - err = nla_parse(cda, ss->cb[cb_id].attr_count, attr, attrlen, |
|---|
| 215 | | - ss->cb[cb_id].policy, extack); |
|---|
| 232 | + err = nla_parse_deprecated(cda, ss->cb[cb_id].attr_count, |
|---|
| 233 | + attr, attrlen, |
|---|
| 234 | + ss->cb[cb_id].policy, extack); |
|---|
| 216 | 235 | if (err < 0) { |
|---|
| 217 | 236 | rcu_read_unlock(); |
|---|
| 218 | 237 | return err; |
|---|
| .. | .. |
|---|
| 314 | 333 | return netlink_ack(skb, nlh, -EINVAL, NULL); |
|---|
| 315 | 334 | replay: |
|---|
| 316 | 335 | status = 0; |
|---|
| 317 | | - |
|---|
| 336 | +replay_abort: |
|---|
| 318 | 337 | skb = netlink_skb_clone(oskb, GFP_KERNEL); |
|---|
| 319 | 338 | if (!skb) |
|---|
| 320 | 339 | return netlink_ack(oskb, nlh, -ENOMEM, NULL); |
|---|
| .. | .. |
|---|
| 426 | 445 | goto ack; |
|---|
| 427 | 446 | } |
|---|
| 428 | 447 | |
|---|
| 429 | | - err = nla_parse(cda, ss->cb[cb_id].attr_count, attr, |
|---|
| 430 | | - attrlen, ss->cb[cb_id].policy, NULL); |
|---|
| 448 | + err = nla_parse_deprecated(cda, |
|---|
| 449 | + ss->cb[cb_id].attr_count, |
|---|
| 450 | + attr, attrlen, |
|---|
| 451 | + ss->cb[cb_id].policy, NULL); |
|---|
| 431 | 452 | if (err < 0) |
|---|
| 432 | 453 | goto ack; |
|---|
| 433 | 454 | |
|---|
| .. | .. |
|---|
| 452 | 473 | * processed, this avoids that the same error is |
|---|
| 453 | 474 | * reported several times when replaying the batch. |
|---|
| 454 | 475 | */ |
|---|
| 455 | | - if (nfnl_err_add(&err_list, nlh, err, &extack) < 0) { |
|---|
| 476 | + if (err == -ENOMEM || |
|---|
| 477 | + nfnl_err_add(&err_list, nlh, err, &extack) < 0) { |
|---|
| 456 | 478 | /* We failed to enqueue an error, reset the |
|---|
| 457 | 479 | * list of errors and send OOM to userspace |
|---|
| 458 | 480 | * pointing to the batch header. |
|---|
| .. | .. |
|---|
| 478 | 500 | } |
|---|
| 479 | 501 | done: |
|---|
| 480 | 502 | if (status & NFNL_BATCH_REPLAY) { |
|---|
| 481 | | - ss->abort(net, oskb); |
|---|
| 503 | + ss->abort(net, oskb, NFNL_ABORT_AUTOLOAD); |
|---|
| 482 | 504 | nfnl_err_reset(&err_list); |
|---|
| 483 | 505 | kfree_skb(skb); |
|---|
| 484 | 506 | module_put(ss->owner); |
|---|
| .. | .. |
|---|
| 489 | 511 | status |= NFNL_BATCH_REPLAY; |
|---|
| 490 | 512 | goto done; |
|---|
| 491 | 513 | } else if (err) { |
|---|
| 492 | | - ss->abort(net, oskb); |
|---|
| 514 | + ss->abort(net, oskb, NFNL_ABORT_NONE); |
|---|
| 493 | 515 | netlink_ack(oskb, nlmsg_hdr(oskb), err, NULL); |
|---|
| 494 | 516 | } |
|---|
| 495 | 517 | } else { |
|---|
| 496 | | - ss->abort(net, oskb); |
|---|
| 518 | + enum nfnl_abort_action abort_action; |
|---|
| 519 | + |
|---|
| 520 | + if (status & NFNL_BATCH_FAILURE) |
|---|
| 521 | + abort_action = NFNL_ABORT_NONE; |
|---|
| 522 | + else |
|---|
| 523 | + abort_action = NFNL_ABORT_VALIDATE; |
|---|
| 524 | + |
|---|
| 525 | + err = ss->abort(net, oskb, abort_action); |
|---|
| 526 | + if (err == -EAGAIN) { |
|---|
| 527 | + nfnl_err_reset(&err_list); |
|---|
| 528 | + kfree_skb(skb); |
|---|
| 529 | + module_put(ss->owner); |
|---|
| 530 | + status |= NFNL_BATCH_FAILURE; |
|---|
| 531 | + goto replay_abort; |
|---|
| 532 | + } |
|---|
| 497 | 533 | } |
|---|
| 498 | | - if (ss->cleanup) |
|---|
| 499 | | - ss->cleanup(net); |
|---|
| 500 | 534 | |
|---|
| 501 | 535 | nfnl_err_deliver(&err_list, oskb); |
|---|
| 502 | 536 | kfree_skb(skb); |
|---|
| .. | .. |
|---|
| 525 | 559 | if (skb->len < NLMSG_HDRLEN + sizeof(struct nfgenmsg)) |
|---|
| 526 | 560 | return; |
|---|
| 527 | 561 | |
|---|
| 528 | | - err = nla_parse(cda, NFNL_BATCH_MAX, attr, attrlen, nfnl_batch_policy, |
|---|
| 529 | | - NULL); |
|---|
| 562 | + err = nla_parse_deprecated(cda, NFNL_BATCH_MAX, attr, attrlen, |
|---|
| 563 | + nfnl_batch_policy, NULL); |
|---|
| 530 | 564 | if (err < 0) { |
|---|
| 531 | 565 | netlink_ack(skb, nlh, err, NULL); |
|---|
| 532 | 566 | return; |
|---|
| .. | .. |
|---|
| 628 | 662 | BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE); |
|---|
| 629 | 663 | |
|---|
| 630 | 664 | for (i=0; i<NFNL_SUBSYS_COUNT; i++) |
|---|
| 631 | | - mutex_init(&table[i].mutex); |
|---|
| 665 | + __mutex_init(&table[i].mutex, nfnl_lockdep_names[i], &nfnl_lockdep_keys[i]); |
|---|
| 632 | 666 | |
|---|
| 633 | 667 | return register_pernet_subsys(&nfnetlink_net_ops); |
|---|
| 634 | 668 | } |
|---|