.. | .. |
---|
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 | } |
---|