diff options
60 files changed, 430 insertions, 352 deletions
diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt b/Documentation/devicetree/bindings/net/dsa/ksz.txt index a700943218ca..ac145b885e95 100644 --- a/Documentation/devicetree/bindings/net/dsa/ksz.txt +++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt | |||
| @@ -4,7 +4,9 @@ Microchip KSZ Series Ethernet switches | |||
| 4 | Required properties: | 4 | Required properties: |
| 5 | 5 | ||
| 6 | - compatible: For external switch chips, compatible string must be exactly one | 6 | - compatible: For external switch chips, compatible string must be exactly one |
| 7 | of: "microchip,ksz9477" | 7 | of the following: |
| 8 | - "microchip,ksz9477" | ||
| 9 | - "microchip,ksz9897" | ||
| 8 | 10 | ||
| 9 | See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional | 11 | See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional |
| 10 | required and optional properties. | 12 | required and optional properties. |
diff --git a/Documentation/devicetree/bindings/net/renesas,ravb.txt b/Documentation/devicetree/bindings/net/renesas,ravb.txt index 19740d01cab0..da249b7c406c 100644 --- a/Documentation/devicetree/bindings/net/renesas,ravb.txt +++ b/Documentation/devicetree/bindings/net/renesas,ravb.txt | |||
| @@ -16,6 +16,7 @@ Required properties: | |||
| 16 | - "renesas,etheravb-rcar-gen2" as a fallback for the above | 16 | - "renesas,etheravb-rcar-gen2" as a fallback for the above |
| 17 | R-Car Gen2 and RZ/G1 devices. | 17 | R-Car Gen2 and RZ/G1 devices. |
| 18 | 18 | ||
| 19 | - "renesas,etheravb-r8a774a1" for the R8A774A1 SoC. | ||
| 19 | - "renesas,etheravb-r8a7795" for the R8A7795 SoC. | 20 | - "renesas,etheravb-r8a7795" for the R8A7795 SoC. |
| 20 | - "renesas,etheravb-r8a7796" for the R8A7796 SoC. | 21 | - "renesas,etheravb-r8a7796" for the R8A7796 SoC. |
| 21 | - "renesas,etheravb-r8a77965" for the R8A77965 SoC. | 22 | - "renesas,etheravb-r8a77965" for the R8A77965 SoC. |
| @@ -24,7 +25,7 @@ Required properties: | |||
| 24 | - "renesas,etheravb-r8a77990" for the R8A77990 SoC. | 25 | - "renesas,etheravb-r8a77990" for the R8A77990 SoC. |
| 25 | - "renesas,etheravb-r8a77995" for the R8A77995 SoC. | 26 | - "renesas,etheravb-r8a77995" for the R8A77995 SoC. |
| 26 | - "renesas,etheravb-rcar-gen3" as a fallback for the above | 27 | - "renesas,etheravb-rcar-gen3" as a fallback for the above |
| 27 | R-Car Gen3 devices. | 28 | R-Car Gen3 and RZ/G2 devices. |
| 28 | 29 | ||
| 29 | When compatible with the generic version, nodes must list the | 30 | When compatible with the generic version, nodes must list the |
| 30 | SoC-specific version corresponding to the platform first followed by | 31 | SoC-specific version corresponding to the platform first followed by |
diff --git a/Documentation/networking/ti-cpsw.txt b/Documentation/networking/ti-cpsw.txt index 67039205bd69..d4d4c0751a09 100644 --- a/Documentation/networking/ti-cpsw.txt +++ b/Documentation/networking/ti-cpsw.txt | |||
| @@ -469,17 +469,18 @@ $ tc -g class show dev eth1 | |||
| 469 | 469 | ||
| 470 | 14) | 470 | 14) |
| 471 | // Set rate for class A - 31 Mbit (tc0, txq2) using CBS Qdisc for Eth1 | 471 | // Set rate for class A - 31 Mbit (tc0, txq2) using CBS Qdisc for Eth1 |
| 472 | // here only idle slope is important, others ignored | 472 | // here only idle slope is important, others ignored, but calculated |
| 473 | // for interface speed - 100Mb for eth1 port. | ||
| 473 | // Set it +1 Mb for reserve (important!) | 474 | // Set it +1 Mb for reserve (important!) |
| 474 | $ tc qdisc add dev eth1 parent 100:3 cbs locredit -1453 \ | 475 | $ tc qdisc add dev eth1 parent 100:3 cbs locredit -1035 \ |
| 475 | hicredit 47 sendslope -969000 idleslope 31000 offload 1 | 476 | hicredit 465 sendslope -69000 idleslope 31000 offload 1 |
| 476 | net eth1: set FIFO3 bw = 31 | 477 | net eth1: set FIFO3 bw = 31 |
| 477 | 478 | ||
| 478 | 15) | 479 | 15) |
| 479 | // Set rate for class B - 11 Mbit (tc1, txq3) using CBS Qdisc for Eth1 | 480 | // Set rate for class B - 11 Mbit (tc1, txq3) using CBS Qdisc for Eth1 |
| 480 | // Set it +1 Mb for reserve (important!) | 481 | // Set it +1 Mb for reserve (important!) |
| 481 | $ tc qdisc add dev eth1 parent 100:4 cbs locredit -1483 \ | 482 | $ tc qdisc add dev eth1 parent 100:4 cbs locredit -1335 \ |
| 482 | hicredit 34 sendslope -989000 idleslope 11000 offload 1 | 483 | hicredit 405 sendslope -89000 idleslope 11000 offload 1 |
| 483 | net eth1: set FIFO2 bw = 11 | 484 | net eth1: set FIFO2 bw = 11 |
| 484 | 485 | ||
| 485 | 16) | 486 | 16) |
diff --git a/Documentation/networking/tproxy.txt b/Documentation/networking/tproxy.txt index ec11429e1d42..b9a188823d9f 100644 --- a/Documentation/networking/tproxy.txt +++ b/Documentation/networking/tproxy.txt | |||
| @@ -5,19 +5,28 @@ This feature adds Linux 2.2-like transparent proxy support to current kernels. | |||
| 5 | To use it, enable the socket match and the TPROXY target in your kernel config. | 5 | To use it, enable the socket match and the TPROXY target in your kernel config. |
| 6 | You will need policy routing too, so be sure to enable that as well. | 6 | You will need policy routing too, so be sure to enable that as well. |
| 7 | 7 | ||
| 8 | From Linux 4.18 transparent proxy support is also available in nf_tables. | ||
| 8 | 9 | ||
| 9 | 1. Making non-local sockets work | 10 | 1. Making non-local sockets work |
| 10 | ================================ | 11 | ================================ |
| 11 | 12 | ||
| 12 | The idea is that you identify packets with destination address matching a local | 13 | The idea is that you identify packets with destination address matching a local |
| 13 | socket on your box, set the packet mark to a certain value, and then match on that | 14 | socket on your box, set the packet mark to a certain value: |
| 14 | value using policy routing to have those packets delivered locally: | ||
| 15 | 15 | ||
| 16 | # iptables -t mangle -N DIVERT | 16 | # iptables -t mangle -N DIVERT |
| 17 | # iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT | 17 | # iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT |
| 18 | # iptables -t mangle -A DIVERT -j MARK --set-mark 1 | 18 | # iptables -t mangle -A DIVERT -j MARK --set-mark 1 |
| 19 | # iptables -t mangle -A DIVERT -j ACCEPT | 19 | # iptables -t mangle -A DIVERT -j ACCEPT |
| 20 | 20 | ||
| 21 | Alternatively you can do this in nft with the following commands: | ||
| 22 | |||
| 23 | # nft add table filter | ||
| 24 | # nft add chain filter divert "{ type filter hook prerouting priority -150; }" | ||
| 25 | # nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept | ||
| 26 | |||
| 27 | And then match on that value using policy routing to have those packets | ||
| 28 | delivered locally: | ||
| 29 | |||
| 21 | # ip rule add fwmark 1 lookup 100 | 30 | # ip rule add fwmark 1 lookup 100 |
| 22 | # ip route add local 0.0.0.0/0 dev lo table 100 | 31 | # ip route add local 0.0.0.0/0 dev lo table 100 |
| 23 | 32 | ||
| @@ -57,17 +66,28 @@ add rules like this to the iptables ruleset above: | |||
| 57 | # iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \ | 66 | # iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \ |
| 58 | --tproxy-mark 0x1/0x1 --on-port 50080 | 67 | --tproxy-mark 0x1/0x1 --on-port 50080 |
| 59 | 68 | ||
| 69 | Or the following rule to nft: | ||
| 70 | |||
| 71 | # nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept | ||
| 72 | |||
| 60 | Note that for this to work you'll have to modify the proxy to enable (SOL_IP, | 73 | Note that for this to work you'll have to modify the proxy to enable (SOL_IP, |
| 61 | IP_TRANSPARENT) for the listening socket. | 74 | IP_TRANSPARENT) for the listening socket. |
| 62 | 75 | ||
| 76 | As an example implementation, tcprdr is available here: | ||
| 77 | https://git.breakpoint.cc/cgit/fw/tcprdr.git/ | ||
| 78 | This tool is written by Florian Westphal and it was used for testing during the | ||
| 79 | nf_tables implementation. | ||
| 63 | 80 | ||
| 64 | 3. Iptables extensions | 81 | 3. Iptables and nf_tables extensions |
| 65 | ====================== | 82 | ==================================== |
| 66 | 83 | ||
| 67 | To use tproxy you'll need to have the 'socket' and 'TPROXY' modules | 84 | To use tproxy you'll need to have the following modules compiled for iptables: |
| 68 | compiled for iptables. A patched version of iptables is available | 85 | - NETFILTER_XT_MATCH_SOCKET |
| 69 | here: http://git.balabit.hu/?p=bazsi/iptables-tproxy.git | 86 | - NETFILTER_XT_TARGET_TPROXY |
| 70 | 87 | ||
| 88 | Or the floowing modules for nf_tables: | ||
| 89 | - NFT_SOCKET | ||
| 90 | - NFT_TPROXY | ||
| 71 | 91 | ||
| 72 | 4. Application support | 92 | 4. Application support |
| 73 | ====================== | 93 | ====================== |
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 7a501dbe7123..6a5b3f00f9ad 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c | |||
| @@ -1640,13 +1640,7 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) | |||
| 1640 | } else | 1640 | } else |
| 1641 | return -EINVAL; | 1641 | return -EINVAL; |
| 1642 | case IIOCDBGVAR: | 1642 | case IIOCDBGVAR: |
| 1643 | if (arg) { | 1643 | return -EINVAL; |
| 1644 | if (copy_to_user(argp, &dev, sizeof(ulong))) | ||
| 1645 | return -EFAULT; | ||
| 1646 | return 0; | ||
| 1647 | } else | ||
| 1648 | return -EINVAL; | ||
| 1649 | break; | ||
| 1650 | default: | 1644 | default: |
| 1651 | if ((cmd & IIOCDRVCTL) == IIOCDRVCTL) | 1645 | if ((cmd & IIOCDRVCTL) == IIOCDRVCTL) |
| 1652 | cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK; | 1646 | cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK; |
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 7210c49b7922..54e0ca6ed730 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c | |||
| @@ -1102,6 +1102,15 @@ static const struct ksz_chip_data ksz_switch_chips[] = { | |||
| 1102 | .cpu_ports = 0x7F, /* can be configured as cpu port */ | 1102 | .cpu_ports = 0x7F, /* can be configured as cpu port */ |
| 1103 | .port_cnt = 7, /* total physical port count */ | 1103 | .port_cnt = 7, /* total physical port count */ |
| 1104 | }, | 1104 | }, |
| 1105 | { | ||
| 1106 | .chip_id = 0x00989700, | ||
| 1107 | .dev_name = "KSZ9897", | ||
| 1108 | .num_vlans = 4096, | ||
| 1109 | .num_alus = 4096, | ||
| 1110 | .num_statics = 16, | ||
| 1111 | .cpu_ports = 0x7F, /* can be configured as cpu port */ | ||
| 1112 | .port_cnt = 7, /* total physical port count */ | ||
| 1113 | }, | ||
| 1105 | }; | 1114 | }; |
| 1106 | 1115 | ||
| 1107 | static int ksz_switch_init(struct ksz_device *dev) | 1116 | static int ksz_switch_init(struct ksz_device *dev) |
diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index c51946983bed..8c1778b42701 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c | |||
| @@ -195,6 +195,7 @@ static int ksz_spi_remove(struct spi_device *spi) | |||
| 195 | 195 | ||
| 196 | static const struct of_device_id ksz_dt_ids[] = { | 196 | static const struct of_device_id ksz_dt_ids[] = { |
| 197 | { .compatible = "microchip,ksz9477" }, | 197 | { .compatible = "microchip,ksz9477" }, |
| 198 | { .compatible = "microchip,ksz9897" }, | ||
| 198 | {}, | 199 | {}, |
| 199 | }; | 200 | }; |
| 200 | MODULE_DEVICE_TABLE(of, ksz_dt_ids); | 201 | MODULE_DEVICE_TABLE(of, ksz_dt_ids); |
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 12fdf5c92b67..6839481f7697 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c | |||
| @@ -848,7 +848,7 @@ static const struct counter_desc pport_per_prio_traffic_stats_desc[] = { | |||
| 848 | 848 | ||
| 849 | #define NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS ARRAY_SIZE(pport_per_prio_traffic_stats_desc) | 849 | #define NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS ARRAY_SIZE(pport_per_prio_traffic_stats_desc) |
| 850 | 850 | ||
| 851 | static int mlx5e_grp_per_prio_traffic_get_num_stats(struct mlx5e_priv *priv) | 851 | static int mlx5e_grp_per_prio_traffic_get_num_stats(void) |
| 852 | { | 852 | { |
| 853 | return NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS * NUM_PPORT_PRIO; | 853 | return NUM_PPORT_PER_PRIO_TRAFFIC_COUNTERS * NUM_PPORT_PRIO; |
| 854 | } | 854 | } |
| @@ -1006,7 +1006,7 @@ static int mlx5e_grp_per_prio_pfc_fill_stats(struct mlx5e_priv *priv, | |||
| 1006 | 1006 | ||
| 1007 | static int mlx5e_grp_per_prio_get_num_stats(struct mlx5e_priv *priv) | 1007 | static int mlx5e_grp_per_prio_get_num_stats(struct mlx5e_priv *priv) |
| 1008 | { | 1008 | { |
| 1009 | return mlx5e_grp_per_prio_traffic_get_num_stats(priv) + | 1009 | return mlx5e_grp_per_prio_traffic_get_num_stats() + |
| 1010 | mlx5e_grp_per_prio_pfc_get_num_stats(priv); | 1010 | mlx5e_grp_per_prio_pfc_get_num_stats(priv); |
| 1011 | } | 1011 | } |
| 1012 | 1012 | ||
diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c index 64dba96edc79..ccdf9123f26f 100644 --- a/drivers/net/ethernet/microchip/lan743x_ptp.c +++ b/drivers/net/ethernet/microchip/lan743x_ptp.c | |||
| @@ -831,8 +831,7 @@ static void lan743x_ptp_sync_to_system_clock(struct lan743x_adapter *adapter) | |||
| 831 | { | 831 | { |
| 832 | struct timespec64 ts; | 832 | struct timespec64 ts; |
| 833 | 833 | ||
| 834 | memset(&ts, 0, sizeof(ts)); | 834 | ktime_get_clocktai_ts64(&ts); |
| 835 | timekeeping_clocktai64(&ts); | ||
| 836 | 835 | ||
| 837 | lan743x_ptp_clock_set(adapter, ts.tv_sec, ts.tv_nsec, 0); | 836 | lan743x_ptp_clock_set(adapter, ts.tv_sec, ts.tv_nsec, 0); |
| 838 | } | 837 | } |
diff --git a/drivers/net/ethernet/realtek/Kconfig b/drivers/net/ethernet/realtek/Kconfig index e1cd934c2e4f..96d1b9c08f1a 100644 --- a/drivers/net/ethernet/realtek/Kconfig +++ b/drivers/net/ethernet/realtek/Kconfig | |||
| @@ -100,6 +100,7 @@ config R8169 | |||
| 100 | select FW_LOADER | 100 | select FW_LOADER |
| 101 | select CRC32 | 101 | select CRC32 |
| 102 | select PHYLIB | 102 | select PHYLIB |
| 103 | select REALTEK_PHY | ||
| 103 | ---help--- | 104 | ---help--- |
| 104 | Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter. | 105 | Say Y here if you have a Realtek 8169 PCI Gigabit Ethernet adapter. |
| 105 | 106 | ||
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 0d9c3831838f..0efa977c422d 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c | |||
| @@ -7071,17 +7071,20 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) | |||
| 7071 | { | 7071 | { |
| 7072 | unsigned int flags; | 7072 | unsigned int flags; |
| 7073 | 7073 | ||
| 7074 | if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { | 7074 | switch (tp->mac_version) { |
| 7075 | case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_06: | ||
| 7075 | RTL_W8(tp, Cfg9346, Cfg9346_Unlock); | 7076 | RTL_W8(tp, Cfg9346, Cfg9346_Unlock); |
| 7076 | RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable); | 7077 | RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable); |
| 7077 | RTL_W8(tp, Cfg9346, Cfg9346_Lock); | 7078 | RTL_W8(tp, Cfg9346, Cfg9346_Lock); |
| 7078 | flags = PCI_IRQ_LEGACY; | 7079 | flags = PCI_IRQ_LEGACY; |
| 7079 | } else if (tp->mac_version == RTL_GIGA_MAC_VER_40) { | 7080 | break; |
| 7081 | case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_40: | ||
| 7080 | /* This version was reported to have issues with resume | 7082 | /* This version was reported to have issues with resume |
| 7081 | * from suspend when using MSI-X | 7083 | * from suspend when using MSI-X |
| 7082 | */ | 7084 | */ |
| 7083 | flags = PCI_IRQ_LEGACY | PCI_IRQ_MSI; | 7085 | flags = PCI_IRQ_LEGACY | PCI_IRQ_MSI; |
| 7084 | } else { | 7086 | break; |
| 7087 | default: | ||
| 7085 | flags = PCI_IRQ_ALL_TYPES; | 7088 | flags = PCI_IRQ_ALL_TYPES; |
| 7086 | } | 7089 | } |
| 7087 | 7090 | ||
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index e3202af72df5..8d679c8b7f25 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
| @@ -789,16 +789,48 @@ static int is_valid_veth_mtu(int mtu) | |||
| 789 | return mtu >= ETH_MIN_MTU && mtu <= ETH_MAX_MTU; | 789 | return mtu >= ETH_MIN_MTU && mtu <= ETH_MAX_MTU; |
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | static int veth_alloc_queues(struct net_device *dev) | ||
| 793 | { | ||
| 794 | struct veth_priv *priv = netdev_priv(dev); | ||
| 795 | int i; | ||
| 796 | |||
| 797 | priv->rq = kcalloc(dev->num_rx_queues, sizeof(*priv->rq), GFP_KERNEL); | ||
| 798 | if (!priv->rq) | ||
| 799 | return -ENOMEM; | ||
| 800 | |||
| 801 | for (i = 0; i < dev->num_rx_queues; i++) | ||
| 802 | priv->rq[i].dev = dev; | ||
| 803 | |||
| 804 | return 0; | ||
| 805 | } | ||
| 806 | |||
| 807 | static void veth_free_queues(struct net_device *dev) | ||
| 808 | { | ||
| 809 | struct veth_priv *priv = netdev_priv(dev); | ||
| 810 | |||
| 811 | kfree(priv->rq); | ||
| 812 | } | ||
| 813 | |||
| 792 | static int veth_dev_init(struct net_device *dev) | 814 | static int veth_dev_init(struct net_device *dev) |
| 793 | { | 815 | { |
| 816 | int err; | ||
| 817 | |||
| 794 | dev->vstats = netdev_alloc_pcpu_stats(struct pcpu_vstats); | 818 | dev->vstats = netdev_alloc_pcpu_stats(struct pcpu_vstats); |
| 795 | if (!dev->vstats) | 819 | if (!dev->vstats) |
| 796 | return -ENOMEM; | 820 | return -ENOMEM; |
| 821 | |||
| 822 | err = veth_alloc_queues(dev); | ||
| 823 | if (err) { | ||
| 824 | free_percpu(dev->vstats); | ||
| 825 | return err; | ||
| 826 | } | ||
| 827 | |||
| 797 | return 0; | 828 | return 0; |
| 798 | } | 829 | } |
| 799 | 830 | ||
| 800 | static void veth_dev_free(struct net_device *dev) | 831 | static void veth_dev_free(struct net_device *dev) |
| 801 | { | 832 | { |
| 833 | veth_free_queues(dev); | ||
| 802 | free_percpu(dev->vstats); | 834 | free_percpu(dev->vstats); |
| 803 | } | 835 | } |
| 804 | 836 | ||
| @@ -1040,31 +1072,13 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[], | |||
| 1040 | return 0; | 1072 | return 0; |
| 1041 | } | 1073 | } |
| 1042 | 1074 | ||
| 1043 | static int veth_alloc_queues(struct net_device *dev) | ||
| 1044 | { | ||
| 1045 | struct veth_priv *priv = netdev_priv(dev); | ||
| 1046 | |||
| 1047 | priv->rq = kcalloc(dev->num_rx_queues, sizeof(*priv->rq), GFP_KERNEL); | ||
| 1048 | if (!priv->rq) | ||
| 1049 | return -ENOMEM; | ||
| 1050 | |||
| 1051 | return 0; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | static void veth_free_queues(struct net_device *dev) | ||
| 1055 | { | ||
| 1056 | struct veth_priv *priv = netdev_priv(dev); | ||
| 1057 | |||
| 1058 | kfree(priv->rq); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | static struct rtnl_link_ops veth_link_ops; | 1075 | static struct rtnl_link_ops veth_link_ops; |
| 1062 | 1076 | ||
| 1063 | static int veth_newlink(struct net *src_net, struct net_device *dev, | 1077 | static int veth_newlink(struct net *src_net, struct net_device *dev, |
| 1064 | struct nlattr *tb[], struct nlattr *data[], | 1078 | struct nlattr *tb[], struct nlattr *data[], |
| 1065 | struct netlink_ext_ack *extack) | 1079 | struct netlink_ext_ack *extack) |
| 1066 | { | 1080 | { |
| 1067 | int err, i; | 1081 | int err; |
| 1068 | struct net_device *peer; | 1082 | struct net_device *peer; |
| 1069 | struct veth_priv *priv; | 1083 | struct veth_priv *priv; |
| 1070 | char ifname[IFNAMSIZ]; | 1084 | char ifname[IFNAMSIZ]; |
| @@ -1117,12 +1131,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
| 1117 | return PTR_ERR(peer); | 1131 | return PTR_ERR(peer); |
| 1118 | } | 1132 | } |
| 1119 | 1133 | ||
| 1120 | err = veth_alloc_queues(peer); | ||
| 1121 | if (err) { | ||
| 1122 | put_net(net); | ||
| 1123 | goto err_peer_alloc_queues; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | if (!ifmp || !tbp[IFLA_ADDRESS]) | 1134 | if (!ifmp || !tbp[IFLA_ADDRESS]) |
| 1127 | eth_hw_addr_random(peer); | 1135 | eth_hw_addr_random(peer); |
| 1128 | 1136 | ||
| @@ -1151,10 +1159,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
| 1151 | * should be re-allocated | 1159 | * should be re-allocated |
| 1152 | */ | 1160 | */ |
| 1153 | 1161 | ||
| 1154 | err = veth_alloc_queues(dev); | ||
| 1155 | if (err) | ||
| 1156 | goto err_alloc_queues; | ||
| 1157 | |||
| 1158 | if (tb[IFLA_ADDRESS] == NULL) | 1162 | if (tb[IFLA_ADDRESS] == NULL) |
| 1159 | eth_hw_addr_random(dev); | 1163 | eth_hw_addr_random(dev); |
| 1160 | 1164 | ||
| @@ -1174,28 +1178,20 @@ static int veth_newlink(struct net *src_net, struct net_device *dev, | |||
| 1174 | */ | 1178 | */ |
| 1175 | 1179 | ||
| 1176 | priv = netdev_priv(dev); | 1180 | priv = netdev_priv(dev); |
| 1177 | for (i = 0; i < dev->real_num_rx_queues; i++) | ||
| 1178 | priv->rq[i].dev = dev; | ||
| 1179 | rcu_assign_pointer(priv->peer, peer); | 1181 | rcu_assign_pointer(priv->peer, peer); |
| 1180 | 1182 | ||
| 1181 | priv = netdev_priv(peer); | 1183 | priv = netdev_priv(peer); |
| 1182 | for (i = 0; i < peer->real_num_rx_queues; i++) | ||
| 1183 | priv->rq[i].dev = peer; | ||
| 1184 | rcu_assign_pointer(priv->peer, dev); | 1184 | rcu_assign_pointer(priv->peer, dev); |
| 1185 | 1185 | ||
| 1186 | return 0; | 1186 | return 0; |
| 1187 | 1187 | ||
| 1188 | err_register_dev: | 1188 | err_register_dev: |
| 1189 | veth_free_queues(dev); | ||
| 1190 | err_alloc_queues: | ||
| 1191 | /* nothing to do */ | 1189 | /* nothing to do */ |
| 1192 | err_configure_peer: | 1190 | err_configure_peer: |
| 1193 | unregister_netdevice(peer); | 1191 | unregister_netdevice(peer); |
| 1194 | return err; | 1192 | return err; |
| 1195 | 1193 | ||
| 1196 | err_register_peer: | 1194 | err_register_peer: |
| 1197 | veth_free_queues(peer); | ||
| 1198 | err_peer_alloc_queues: | ||
| 1199 | free_netdev(peer); | 1195 | free_netdev(peer); |
| 1200 | return err; | 1196 | return err; |
| 1201 | } | 1197 | } |
diff --git a/include/linux/filter.h b/include/linux/filter.h index 5d565c50bcb2..6791a0ac0139 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h | |||
| @@ -543,7 +543,6 @@ struct bpf_redirect_info { | |||
| 543 | u32 flags; | 543 | u32 flags; |
| 544 | struct bpf_map *map; | 544 | struct bpf_map *map; |
| 545 | struct bpf_map *map_to_flush; | 545 | struct bpf_map *map_to_flush; |
| 546 | unsigned long map_owner; | ||
| 547 | u32 kern_flags; | 546 | u32 kern_flags; |
| 548 | }; | 547 | }; |
| 549 | 548 | ||
| @@ -781,6 +780,8 @@ static inline bool bpf_dump_raw_ok(void) | |||
| 781 | struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, | 780 | struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, |
| 782 | const struct bpf_insn *patch, u32 len); | 781 | const struct bpf_insn *patch, u32 len); |
| 783 | 782 | ||
| 783 | void bpf_clear_redirect_map(struct bpf_map *map); | ||
| 784 | |||
| 784 | static inline bool xdp_return_frame_no_direct(void) | 785 | static inline bool xdp_return_frame_no_direct(void) |
| 785 | { | 786 | { |
| 786 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); | 787 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); |
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index a27cf6652327..fa928242567d 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h | |||
| @@ -447,6 +447,11 @@ static inline clock_t jiffies_delta_to_clock_t(long delta) | |||
| 447 | return jiffies_to_clock_t(max(0L, delta)); | 447 | return jiffies_to_clock_t(max(0L, delta)); |
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | static inline unsigned int jiffies_delta_to_msecs(long delta) | ||
| 451 | { | ||
| 452 | return jiffies_to_msecs(max(0L, delta)); | ||
| 453 | } | ||
| 454 | |||
| 450 | extern unsigned long clock_t_to_jiffies(unsigned long x); | 455 | extern unsigned long clock_t_to_jiffies(unsigned long x); |
| 451 | extern u64 jiffies_64_to_clock_t(u64 x); | 456 | extern u64 jiffies_64_to_clock_t(u64 x); |
| 452 | extern u64 nsec_to_clock_t(u64 x); | 457 | extern u64 nsec_to_clock_t(u64 x); |
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 3190997df9ca..e089157dcf97 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
| @@ -451,9 +451,20 @@ extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock, | |||
| 451 | #define atomic_dec_and_lock_irqsave(atomic, lock, flags) \ | 451 | #define atomic_dec_and_lock_irqsave(atomic, lock, flags) \ |
| 452 | __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags))) | 452 | __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags))) |
| 453 | 453 | ||
| 454 | int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask, | 454 | int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask, |
| 455 | size_t max_size, unsigned int cpu_mult, | 455 | size_t max_size, unsigned int cpu_mult, |
| 456 | gfp_t gfp); | 456 | gfp_t gfp, const char *name, |
| 457 | struct lock_class_key *key); | ||
| 458 | |||
| 459 | #define alloc_bucket_spinlocks(locks, lock_mask, max_size, cpu_mult, gfp) \ | ||
| 460 | ({ \ | ||
| 461 | static struct lock_class_key key; \ | ||
| 462 | int ret; \ | ||
| 463 | \ | ||
| 464 | ret = __alloc_bucket_spinlocks(locks, lock_mask, max_size, \ | ||
| 465 | cpu_mult, gfp, #locks, &key); \ | ||
| 466 | ret; \ | ||
| 467 | }) | ||
| 457 | 468 | ||
| 458 | void free_bucket_spinlocks(spinlock_t *locks); | 469 | void free_bucket_spinlocks(spinlock_t *locks); |
| 459 | 470 | ||
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index dc417ef0a0c5..0f39ac487012 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
| @@ -274,7 +274,7 @@ enum nft_set_class { | |||
| 274 | * @space: memory class | 274 | * @space: memory class |
| 275 | */ | 275 | */ |
| 276 | struct nft_set_estimate { | 276 | struct nft_set_estimate { |
| 277 | unsigned int size; | 277 | u64 size; |
| 278 | enum nft_set_class lookup; | 278 | enum nft_set_class lookup; |
| 279 | enum nft_set_class space; | 279 | enum nft_set_class space; |
| 280 | }; | 280 | }; |
| @@ -336,7 +336,7 @@ struct nft_set_ops { | |||
| 336 | const struct nft_set_elem *elem, | 336 | const struct nft_set_elem *elem, |
| 337 | unsigned int flags); | 337 | unsigned int flags); |
| 338 | 338 | ||
| 339 | unsigned int (*privsize)(const struct nlattr * const nla[], | 339 | u64 (*privsize)(const struct nlattr * const nla[], |
| 340 | const struct nft_set_desc *desc); | 340 | const struct nft_set_desc *desc); |
| 341 | bool (*estimate)(const struct nft_set_desc *desc, | 341 | bool (*estimate)(const struct nft_set_desc *desc, |
| 342 | u32 features, | 342 | u32 features, |
| @@ -1374,6 +1374,6 @@ struct nft_trans_flowtable { | |||
| 1374 | (((struct nft_trans_flowtable *)trans->data)->flowtable) | 1374 | (((struct nft_trans_flowtable *)trans->data)->flowtable) |
| 1375 | 1375 | ||
| 1376 | int __init nft_chain_filter_init(void); | 1376 | int __init nft_chain_filter_init(void); |
| 1377 | void __exit nft_chain_filter_fini(void); | 1377 | void nft_chain_filter_fini(void); |
| 1378 | 1378 | ||
| 1379 | #endif /* _NET_NF_TABLES_H */ | 1379 | #endif /* _NET_NF_TABLES_H */ |
diff --git a/include/net/tcp.h b/include/net/tcp.h index d196901c9dba..770917d0caa7 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
| @@ -2065,6 +2065,10 @@ int tcp_set_ulp_id(struct sock *sk, const int ulp); | |||
| 2065 | void tcp_get_available_ulp(char *buf, size_t len); | 2065 | void tcp_get_available_ulp(char *buf, size_t len); |
| 2066 | void tcp_cleanup_ulp(struct sock *sk); | 2066 | void tcp_cleanup_ulp(struct sock *sk); |
| 2067 | 2067 | ||
| 2068 | #define MODULE_ALIAS_TCP_ULP(name) \ | ||
| 2069 | __MODULE_INFO(alias, alias_userspace, name); \ | ||
| 2070 | __MODULE_INFO(alias, alias_tcp_ulp, "tcp-ulp-" name) | ||
| 2071 | |||
| 2068 | /* Call BPF_SOCK_OPS program that returns an int. If the return value | 2072 | /* Call BPF_SOCK_OPS program that returns an int. If the return value |
| 2069 | * is < 0, then the BPF op failed (for example if the loaded BPF | 2073 | * is < 0, then the BPF op failed (for example if the loaded BPF |
| 2070 | * program does not support the chosen operation or there is no BPF | 2074 | * program does not support the chosen operation or there is no BPF |
diff --git a/include/trace/events/xdp.h b/include/trace/events/xdp.h index 1ecf4c67fcf7..e95cb86b65cf 100644 --- a/include/trace/events/xdp.h +++ b/include/trace/events/xdp.h | |||
| @@ -147,9 +147,8 @@ struct _bpf_dtab_netdev { | |||
| 147 | 147 | ||
| 148 | #define devmap_ifindex(fwd, map) \ | 148 | #define devmap_ifindex(fwd, map) \ |
| 149 | (!fwd ? 0 : \ | 149 | (!fwd ? 0 : \ |
| 150 | (!map ? 0 : \ | 150 | ((map->map_type == BPF_MAP_TYPE_DEVMAP) ? \ |
| 151 | ((map->map_type == BPF_MAP_TYPE_DEVMAP) ? \ | 151 | ((struct _bpf_dtab_netdev *)fwd)->dev->ifindex : 0)) |
| 152 | ((struct _bpf_dtab_netdev *)fwd)->dev->ifindex : 0))) | ||
| 153 | 152 | ||
| 154 | #define _trace_xdp_redirect_map(dev, xdp, fwd, map, idx) \ | 153 | #define _trace_xdp_redirect_map(dev, xdp, fwd, map, idx) \ |
| 155 | trace_xdp_redirect_map(dev, xdp, devmap_ifindex(fwd, map), \ | 154 | trace_xdp_redirect_map(dev, xdp, devmap_ifindex(fwd, map), \ |
diff --git a/include/uapi/linux/netfilter/nfnetlink_osf.h b/include/uapi/linux/netfilter/nfnetlink_osf.h index 76a3527df5dd..272bc3195f2d 100644 --- a/include/uapi/linux/netfilter/nfnetlink_osf.h +++ b/include/uapi/linux/netfilter/nfnetlink_osf.h | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | #define _NF_OSF_H | 2 | #define _NF_OSF_H |
| 3 | 3 | ||
| 4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
| 5 | #include <linux/ip.h> | ||
| 6 | #include <linux/tcp.h> | ||
| 5 | 7 | ||
| 6 | #define MAXGENRELEN 32 | 8 | #define MAXGENRELEN 32 |
| 7 | 9 | ||
diff --git a/include/uapi/linux/netfilter/xt_osf.h b/include/uapi/linux/netfilter/xt_osf.h index 24102b5286ec..6e466236ca4b 100644 --- a/include/uapi/linux/netfilter/xt_osf.h +++ b/include/uapi/linux/netfilter/xt_osf.h | |||
| @@ -21,8 +21,6 @@ | |||
| 21 | #define _XT_OSF_H | 21 | #define _XT_OSF_H |
| 22 | 22 | ||
| 23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
| 24 | #include <linux/ip.h> | ||
| 25 | #include <linux/tcp.h> | ||
| 26 | #include <linux/netfilter/nfnetlink_osf.h> | 24 | #include <linux/netfilter/nfnetlink_osf.h> |
| 27 | 25 | ||
| 28 | #define XT_OSF_GENRE NF_OSF_GENRE | 26 | #define XT_OSF_GENRE NF_OSF_GENRE |
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 4d09e610777f..3f5bf1af0826 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c | |||
| @@ -1579,7 +1579,7 @@ static bool bpf_prog_array_copy_core(struct bpf_prog_array __rcu *array, | |||
| 1579 | struct bpf_prog_array_item *item; | 1579 | struct bpf_prog_array_item *item; |
| 1580 | int i = 0; | 1580 | int i = 0; |
| 1581 | 1581 | ||
| 1582 | item = rcu_dereference(array)->items; | 1582 | item = rcu_dereference_check(array, 1)->items; |
| 1583 | for (; item->prog; item++) { | 1583 | for (; item->prog; item++) { |
| 1584 | if (item->prog == &dummy_bpf_prog.prog) | 1584 | if (item->prog == &dummy_bpf_prog.prog) |
| 1585 | continue; | 1585 | continue; |
diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c index 620bc5024d7d..24aac0d0f412 100644 --- a/kernel/bpf/cpumap.c +++ b/kernel/bpf/cpumap.c | |||
| @@ -479,6 +479,8 @@ static void cpu_map_free(struct bpf_map *map) | |||
| 479 | * It does __not__ ensure pending flush operations (if any) are | 479 | * It does __not__ ensure pending flush operations (if any) are |
| 480 | * complete. | 480 | * complete. |
| 481 | */ | 481 | */ |
| 482 | |||
| 483 | bpf_clear_redirect_map(map); | ||
| 482 | synchronize_rcu(); | 484 | synchronize_rcu(); |
| 483 | 485 | ||
| 484 | /* To ensure all pending flush operations have completed wait for flush | 486 | /* To ensure all pending flush operations have completed wait for flush |
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c index ac1df79f3788..141710b82a6c 100644 --- a/kernel/bpf/devmap.c +++ b/kernel/bpf/devmap.c | |||
| @@ -161,6 +161,7 @@ static void dev_map_free(struct bpf_map *map) | |||
| 161 | list_del_rcu(&dtab->list); | 161 | list_del_rcu(&dtab->list); |
| 162 | spin_unlock(&dev_map_lock); | 162 | spin_unlock(&dev_map_lock); |
| 163 | 163 | ||
| 164 | bpf_clear_redirect_map(map); | ||
| 164 | synchronize_rcu(); | 165 | synchronize_rcu(); |
| 165 | 166 | ||
| 166 | /* To ensure all pending flush operations have completed wait for flush | 167 | /* To ensure all pending flush operations have completed wait for flush |
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 0c1a696b041b..98e621a29e8e 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c | |||
| @@ -58,6 +58,7 @@ struct bpf_stab { | |||
| 58 | struct bpf_map map; | 58 | struct bpf_map map; |
| 59 | struct sock **sock_map; | 59 | struct sock **sock_map; |
| 60 | struct bpf_sock_progs progs; | 60 | struct bpf_sock_progs progs; |
| 61 | raw_spinlock_t lock; | ||
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | struct bucket { | 64 | struct bucket { |
| @@ -89,9 +90,9 @@ enum smap_psock_state { | |||
| 89 | 90 | ||
| 90 | struct smap_psock_map_entry { | 91 | struct smap_psock_map_entry { |
| 91 | struct list_head list; | 92 | struct list_head list; |
| 93 | struct bpf_map *map; | ||
| 92 | struct sock **entry; | 94 | struct sock **entry; |
| 93 | struct htab_elem __rcu *hash_link; | 95 | struct htab_elem __rcu *hash_link; |
| 94 | struct bpf_htab __rcu *htab; | ||
| 95 | }; | 96 | }; |
| 96 | 97 | ||
| 97 | struct smap_psock { | 98 | struct smap_psock { |
| @@ -343,13 +344,18 @@ static void bpf_tcp_close(struct sock *sk, long timeout) | |||
| 343 | e = psock_map_pop(sk, psock); | 344 | e = psock_map_pop(sk, psock); |
| 344 | while (e) { | 345 | while (e) { |
| 345 | if (e->entry) { | 346 | if (e->entry) { |
| 346 | osk = cmpxchg(e->entry, sk, NULL); | 347 | struct bpf_stab *stab = container_of(e->map, struct bpf_stab, map); |
| 348 | |||
| 349 | raw_spin_lock_bh(&stab->lock); | ||
| 350 | osk = *e->entry; | ||
| 347 | if (osk == sk) { | 351 | if (osk == sk) { |
| 352 | *e->entry = NULL; | ||
| 348 | smap_release_sock(psock, sk); | 353 | smap_release_sock(psock, sk); |
| 349 | } | 354 | } |
| 355 | raw_spin_unlock_bh(&stab->lock); | ||
| 350 | } else { | 356 | } else { |
| 351 | struct htab_elem *link = rcu_dereference(e->hash_link); | 357 | struct htab_elem *link = rcu_dereference(e->hash_link); |
| 352 | struct bpf_htab *htab = rcu_dereference(e->htab); | 358 | struct bpf_htab *htab = container_of(e->map, struct bpf_htab, map); |
| 353 | struct hlist_head *head; | 359 | struct hlist_head *head; |
| 354 | struct htab_elem *l; | 360 | struct htab_elem *l; |
| 355 | struct bucket *b; | 361 | struct bucket *b; |
| @@ -370,6 +376,7 @@ static void bpf_tcp_close(struct sock *sk, long timeout) | |||
| 370 | } | 376 | } |
| 371 | raw_spin_unlock_bh(&b->lock); | 377 | raw_spin_unlock_bh(&b->lock); |
| 372 | } | 378 | } |
| 379 | kfree(e); | ||
| 373 | e = psock_map_pop(sk, psock); | 380 | e = psock_map_pop(sk, psock); |
| 374 | } | 381 | } |
| 375 | rcu_read_unlock(); | 382 | rcu_read_unlock(); |
| @@ -1641,6 +1648,7 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr) | |||
| 1641 | return ERR_PTR(-ENOMEM); | 1648 | return ERR_PTR(-ENOMEM); |
| 1642 | 1649 | ||
| 1643 | bpf_map_init_from_attr(&stab->map, attr); | 1650 | bpf_map_init_from_attr(&stab->map, attr); |
| 1651 | raw_spin_lock_init(&stab->lock); | ||
| 1644 | 1652 | ||
| 1645 | /* make sure page count doesn't overflow */ | 1653 | /* make sure page count doesn't overflow */ |
| 1646 | cost = (u64) stab->map.max_entries * sizeof(struct sock *); | 1654 | cost = (u64) stab->map.max_entries * sizeof(struct sock *); |
| @@ -1675,8 +1683,10 @@ static void smap_list_map_remove(struct smap_psock *psock, | |||
| 1675 | 1683 | ||
| 1676 | spin_lock_bh(&psock->maps_lock); | 1684 | spin_lock_bh(&psock->maps_lock); |
| 1677 | list_for_each_entry_safe(e, tmp, &psock->maps, list) { | 1685 | list_for_each_entry_safe(e, tmp, &psock->maps, list) { |
| 1678 | if (e->entry == entry) | 1686 | if (e->entry == entry) { |
| 1679 | list_del(&e->list); | 1687 | list_del(&e->list); |
| 1688 | kfree(e); | ||
| 1689 | } | ||
| 1680 | } | 1690 | } |
| 1681 | spin_unlock_bh(&psock->maps_lock); | 1691 | spin_unlock_bh(&psock->maps_lock); |
| 1682 | } | 1692 | } |
| @@ -1690,8 +1700,10 @@ static void smap_list_hash_remove(struct smap_psock *psock, | |||
| 1690 | list_for_each_entry_safe(e, tmp, &psock->maps, list) { | 1700 | list_for_each_entry_safe(e, tmp, &psock->maps, list) { |
| 1691 | struct htab_elem *c = rcu_dereference(e->hash_link); | 1701 | struct htab_elem *c = rcu_dereference(e->hash_link); |
| 1692 | 1702 | ||
| 1693 | if (c == hash_link) | 1703 | if (c == hash_link) { |
| 1694 | list_del(&e->list); | 1704 | list_del(&e->list); |
| 1705 | kfree(e); | ||
| 1706 | } | ||
| 1695 | } | 1707 | } |
| 1696 | spin_unlock_bh(&psock->maps_lock); | 1708 | spin_unlock_bh(&psock->maps_lock); |
| 1697 | } | 1709 | } |
| @@ -1711,14 +1723,15 @@ static void sock_map_free(struct bpf_map *map) | |||
| 1711 | * and a grace period expire to ensure psock is really safe to remove. | 1723 | * and a grace period expire to ensure psock is really safe to remove. |
| 1712 | */ | 1724 | */ |
| 1713 | rcu_read_lock(); | 1725 | rcu_read_lock(); |
| 1726 | raw_spin_lock_bh(&stab->lock); | ||
| 1714 | for (i = 0; i < stab->map.max_entries; i++) { | 1727 | for (i = 0; i < stab->map.max_entries; i++) { |
| 1715 | struct smap_psock *psock; | 1728 | struct smap_psock *psock; |
| 1716 | struct sock *sock; | 1729 | struct sock *sock; |
| 1717 | 1730 | ||
| 1718 | sock = xchg(&stab->sock_map[i], NULL); | 1731 | sock = stab->sock_map[i]; |
| 1719 | if (!sock) | 1732 | if (!sock) |
| 1720 | continue; | 1733 | continue; |
| 1721 | 1734 | stab->sock_map[i] = NULL; | |
| 1722 | psock = smap_psock_sk(sock); | 1735 | psock = smap_psock_sk(sock); |
| 1723 | /* This check handles a racing sock event that can get the | 1736 | /* This check handles a racing sock event that can get the |
| 1724 | * sk_callback_lock before this case but after xchg happens | 1737 | * sk_callback_lock before this case but after xchg happens |
| @@ -1730,6 +1743,7 @@ static void sock_map_free(struct bpf_map *map) | |||
| 1730 | smap_release_sock(psock, sock); | 1743 | smap_release_sock(psock, sock); |
| 1731 | } | 1744 | } |
| 1732 | } | 1745 | } |
| 1746 | raw_spin_unlock_bh(&stab->lock); | ||
| 1733 | rcu_read_unlock(); | 1747 | rcu_read_unlock(); |
| 1734 | 1748 | ||
| 1735 | sock_map_remove_complete(stab); | 1749 | sock_map_remove_complete(stab); |
| @@ -1773,19 +1787,23 @@ static int sock_map_delete_elem(struct bpf_map *map, void *key) | |||
| 1773 | if (k >= map->max_entries) | 1787 | if (k >= map->max_entries) |
| 1774 | return -EINVAL; | 1788 | return -EINVAL; |
| 1775 | 1789 | ||
| 1776 | sock = xchg(&stab->sock_map[k], NULL); | 1790 | raw_spin_lock_bh(&stab->lock); |
| 1791 | sock = stab->sock_map[k]; | ||
| 1792 | stab->sock_map[k] = NULL; | ||
| 1793 | raw_spin_unlock_bh(&stab->lock); | ||
| 1777 | if (!sock) | 1794 | if (!sock) |
| 1778 | return -EINVAL; | 1795 | return -EINVAL; |
| 1779 | 1796 | ||
| 1780 | psock = smap_psock_sk(sock); | 1797 | psock = smap_psock_sk(sock); |
| 1781 | if (!psock) | 1798 | if (!psock) |
| 1782 | goto out; | 1799 | return 0; |
| 1783 | 1800 | if (psock->bpf_parse) { | |
| 1784 | if (psock->bpf_parse) | 1801 | write_lock_bh(&sock->sk_callback_lock); |
| 1785 | smap_stop_sock(psock, sock); | 1802 | smap_stop_sock(psock, sock); |
| 1803 | write_unlock_bh(&sock->sk_callback_lock); | ||
| 1804 | } | ||
| 1786 | smap_list_map_remove(psock, &stab->sock_map[k]); | 1805 | smap_list_map_remove(psock, &stab->sock_map[k]); |
| 1787 | smap_release_sock(psock, sock); | 1806 | smap_release_sock(psock, sock); |
| 1788 | out: | ||
| 1789 | return 0; | 1807 | return 0; |
| 1790 | } | 1808 | } |
| 1791 | 1809 | ||
| @@ -1821,11 +1839,9 @@ out: | |||
| 1821 | static int __sock_map_ctx_update_elem(struct bpf_map *map, | 1839 | static int __sock_map_ctx_update_elem(struct bpf_map *map, |
| 1822 | struct bpf_sock_progs *progs, | 1840 | struct bpf_sock_progs *progs, |
| 1823 | struct sock *sock, | 1841 | struct sock *sock, |
| 1824 | struct sock **map_link, | ||
| 1825 | void *key) | 1842 | void *key) |
| 1826 | { | 1843 | { |
| 1827 | struct bpf_prog *verdict, *parse, *tx_msg; | 1844 | struct bpf_prog *verdict, *parse, *tx_msg; |
| 1828 | struct smap_psock_map_entry *e = NULL; | ||
| 1829 | struct smap_psock *psock; | 1845 | struct smap_psock *psock; |
| 1830 | bool new = false; | 1846 | bool new = false; |
| 1831 | int err = 0; | 1847 | int err = 0; |
| @@ -1898,14 +1914,6 @@ static int __sock_map_ctx_update_elem(struct bpf_map *map, | |||
| 1898 | new = true; | 1914 | new = true; |
| 1899 | } | 1915 | } |
| 1900 | 1916 | ||
| 1901 | if (map_link) { | ||
| 1902 | e = kzalloc(sizeof(*e), GFP_ATOMIC | __GFP_NOWARN); | ||
| 1903 | if (!e) { | ||
| 1904 | err = -ENOMEM; | ||
| 1905 | goto out_free; | ||
| 1906 | } | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | /* 3. At this point we have a reference to a valid psock that is | 1917 | /* 3. At this point we have a reference to a valid psock that is |
| 1910 | * running. Attach any BPF programs needed. | 1918 | * running. Attach any BPF programs needed. |
| 1911 | */ | 1919 | */ |
| @@ -1927,17 +1935,6 @@ static int __sock_map_ctx_update_elem(struct bpf_map *map, | |||
| 1927 | write_unlock_bh(&sock->sk_callback_lock); | 1935 | write_unlock_bh(&sock->sk_callback_lock); |
| 1928 | } | 1936 | } |
| 1929 | 1937 | ||
| 1930 | /* 4. Place psock in sockmap for use and stop any programs on | ||
| 1931 | * the old sock assuming its not the same sock we are replacing | ||
| 1932 | * it with. Because we can only have a single set of programs if | ||
| 1933 | * old_sock has a strp we can stop it. | ||
| 1934 | */ | ||
| 1935 | if (map_link) { | ||
| 1936 | e->entry = map_link; | ||
| 1937 | spin_lock_bh(&psock->maps_lock); | ||
| 1938 | list_add_tail(&e->list, &psock->maps); | ||
| 1939 | spin_unlock_bh(&psock->maps_lock); | ||
| 1940 | } | ||
| 1941 | return err; | 1938 | return err; |
| 1942 | out_free: | 1939 | out_free: |
| 1943 | smap_release_sock(psock, sock); | 1940 | smap_release_sock(psock, sock); |
| @@ -1948,7 +1945,6 @@ out_progs: | |||
| 1948 | } | 1945 | } |
| 1949 | if (tx_msg) | 1946 | if (tx_msg) |
| 1950 | bpf_prog_put(tx_msg); | 1947 | bpf_prog_put(tx_msg); |
| 1951 | kfree(e); | ||
| 1952 | return err; | 1948 | return err; |
| 1953 | } | 1949 | } |
| 1954 | 1950 | ||
| @@ -1958,36 +1954,57 @@ static int sock_map_ctx_update_elem(struct bpf_sock_ops_kern *skops, | |||
| 1958 | { | 1954 | { |
| 1959 | struct bpf_stab *stab = container_of(map, struct bpf_stab, map); | 1955 | struct bpf_stab *stab = container_of(map, struct bpf_stab, map); |
| 1960 | struct bpf_sock_progs *progs = &stab->progs; | 1956 | struct bpf_sock_progs *progs = &stab->progs; |
| 1961 | struct sock *osock, *sock; | 1957 | struct sock *osock, *sock = skops->sk; |
| 1958 | struct smap_psock_map_entry *e; | ||
| 1959 | struct smap_psock *psock; | ||
| 1962 | u32 i = *(u32 *)key; | 1960 | u32 i = *(u32 *)key; |
| 1963 | int err; | 1961 | int err; |
| 1964 | 1962 | ||
| 1965 | if (unlikely(flags > BPF_EXIST)) | 1963 | if (unlikely(flags > BPF_EXIST)) |
| 1966 | return -EINVAL; | 1964 | return -EINVAL; |
| 1967 | |||
| 1968 | if (unlikely(i >= stab->map.max_entries)) | 1965 | if (unlikely(i >= stab->map.max_entries)) |
| 1969 | return -E2BIG; | 1966 | return -E2BIG; |
| 1970 | 1967 | ||
| 1971 | sock = READ_ONCE(stab->sock_map[i]); | 1968 | e = kzalloc(sizeof(*e), GFP_ATOMIC | __GFP_NOWARN); |
| 1972 | if (flags == BPF_EXIST && !sock) | 1969 | if (!e) |
| 1973 | return -ENOENT; | 1970 | return -ENOMEM; |
| 1974 | else if (flags == BPF_NOEXIST && sock) | ||
| 1975 | return -EEXIST; | ||
| 1976 | 1971 | ||
| 1977 | sock = skops->sk; | 1972 | err = __sock_map_ctx_update_elem(map, progs, sock, key); |
| 1978 | err = __sock_map_ctx_update_elem(map, progs, sock, &stab->sock_map[i], | ||
| 1979 | key); | ||
| 1980 | if (err) | 1973 | if (err) |
| 1981 | goto out; | 1974 | goto out; |
| 1982 | 1975 | ||
| 1983 | osock = xchg(&stab->sock_map[i], sock); | 1976 | /* psock guaranteed to be present. */ |
| 1984 | if (osock) { | 1977 | psock = smap_psock_sk(sock); |
| 1985 | struct smap_psock *opsock = smap_psock_sk(osock); | 1978 | raw_spin_lock_bh(&stab->lock); |
| 1979 | osock = stab->sock_map[i]; | ||
| 1980 | if (osock && flags == BPF_NOEXIST) { | ||
| 1981 | err = -EEXIST; | ||
| 1982 | goto out_unlock; | ||
| 1983 | } | ||
| 1984 | if (!osock && flags == BPF_EXIST) { | ||
| 1985 | err = -ENOENT; | ||
| 1986 | goto out_unlock; | ||
| 1987 | } | ||
| 1986 | 1988 | ||
| 1987 | smap_list_map_remove(opsock, &stab->sock_map[i]); | 1989 | e->entry = &stab->sock_map[i]; |
| 1988 | smap_release_sock(opsock, osock); | 1990 | e->map = map; |
| 1991 | spin_lock_bh(&psock->maps_lock); | ||
| 1992 | list_add_tail(&e->list, &psock->maps); | ||
| 1993 | spin_unlock_bh(&psock->maps_lock); | ||
| 1994 | |||
| 1995 | stab->sock_map[i] = sock; | ||
| 1996 | if (osock) { | ||
| 1997 | psock = smap_psock_sk(osock); | ||
| 1998 | smap_list_map_remove(psock, &stab->sock_map[i]); | ||
| 1999 | smap_release_sock(psock, osock); | ||
| 1989 | } | 2000 | } |
| 2001 | raw_spin_unlock_bh(&stab->lock); | ||
| 2002 | return 0; | ||
| 2003 | out_unlock: | ||
| 2004 | smap_release_sock(psock, sock); | ||
| 2005 | raw_spin_unlock_bh(&stab->lock); | ||
| 1990 | out: | 2006 | out: |
| 2007 | kfree(e); | ||
| 1991 | return err; | 2008 | return err; |
| 1992 | } | 2009 | } |
| 1993 | 2010 | ||
| @@ -2350,7 +2367,7 @@ static int sock_hash_ctx_update_elem(struct bpf_sock_ops_kern *skops, | |||
| 2350 | b = __select_bucket(htab, hash); | 2367 | b = __select_bucket(htab, hash); |
| 2351 | head = &b->head; | 2368 | head = &b->head; |
| 2352 | 2369 | ||
| 2353 | err = __sock_map_ctx_update_elem(map, progs, sock, NULL, key); | 2370 | err = __sock_map_ctx_update_elem(map, progs, sock, key); |
| 2354 | if (err) | 2371 | if (err) |
| 2355 | goto err; | 2372 | goto err; |
| 2356 | 2373 | ||
| @@ -2376,8 +2393,7 @@ static int sock_hash_ctx_update_elem(struct bpf_sock_ops_kern *skops, | |||
| 2376 | } | 2393 | } |
| 2377 | 2394 | ||
| 2378 | rcu_assign_pointer(e->hash_link, l_new); | 2395 | rcu_assign_pointer(e->hash_link, l_new); |
| 2379 | rcu_assign_pointer(e->htab, | 2396 | e->map = map; |
| 2380 | container_of(map, struct bpf_htab, map)); | ||
| 2381 | spin_lock_bh(&psock->maps_lock); | 2397 | spin_lock_bh(&psock->maps_lock); |
| 2382 | list_add_tail(&e->list, &psock->maps); | 2398 | list_add_tail(&e->list, &psock->maps); |
| 2383 | spin_unlock_bh(&psock->maps_lock); | 2399 | spin_unlock_bh(&psock->maps_lock); |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ca90679a7fe5..92246117d2b0 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
| @@ -5844,27 +5844,6 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) | |||
| 5844 | goto patch_call_imm; | 5844 | goto patch_call_imm; |
| 5845 | } | 5845 | } |
| 5846 | 5846 | ||
| 5847 | if (insn->imm == BPF_FUNC_redirect_map) { | ||
| 5848 | /* Note, we cannot use prog directly as imm as subsequent | ||
| 5849 | * rewrites would still change the prog pointer. The only | ||
| 5850 | * stable address we can use is aux, which also works with | ||
| 5851 | * prog clones during blinding. | ||
| 5852 | */ | ||
| 5853 | u64 addr = (unsigned long)prog->aux; | ||
| 5854 | struct bpf_insn r4_ld[] = { | ||
| 5855 | BPF_LD_IMM64(BPF_REG_4, addr), | ||
| 5856 | *insn, | ||
| 5857 | }; | ||
| 5858 | cnt = ARRAY_SIZE(r4_ld); | ||
| 5859 | |||
| 5860 | new_prog = bpf_patch_insn_data(env, i + delta, r4_ld, cnt); | ||
| 5861 | if (!new_prog) | ||
| 5862 | return -ENOMEM; | ||
| 5863 | |||
| 5864 | delta += cnt - 1; | ||
| 5865 | env->prog = prog = new_prog; | ||
| 5866 | insn = new_prog->insnsi + i + delta; | ||
| 5867 | } | ||
| 5868 | patch_call_imm: | 5847 | patch_call_imm: |
| 5869 | fn = env->ops->get_func_proto(insn->imm, env->prog); | 5848 | fn = env->ops->get_func_proto(insn->imm, env->prog); |
| 5870 | /* all functions that have prototype and verifier allowed | 5849 | /* all functions that have prototype and verifier allowed |
diff --git a/kernel/bpf/xskmap.c b/kernel/bpf/xskmap.c index 4ddf61e158f6..9f8463afda9c 100644 --- a/kernel/bpf/xskmap.c +++ b/kernel/bpf/xskmap.c | |||
| @@ -75,6 +75,7 @@ static void xsk_map_free(struct bpf_map *map) | |||
| 75 | struct xsk_map *m = container_of(map, struct xsk_map, map); | 75 | struct xsk_map *m = container_of(map, struct xsk_map, map); |
| 76 | int i; | 76 | int i; |
| 77 | 77 | ||
| 78 | bpf_clear_redirect_map(map); | ||
| 78 | synchronize_net(); | 79 | synchronize_net(); |
| 79 | 80 | ||
| 80 | for (i = 0; i < map->max_entries; i++) { | 81 | for (i = 0; i < map->max_entries; i++) { |
diff --git a/lib/bucket_locks.c b/lib/bucket_locks.c index ade3ce6c4af6..64b92e1dbace 100644 --- a/lib/bucket_locks.c +++ b/lib/bucket_locks.c | |||
| @@ -11,8 +11,9 @@ | |||
| 11 | * to a power of 2 to be suitable as a hash table. | 11 | * to a power of 2 to be suitable as a hash table. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask, | 14 | int __alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask, |
| 15 | size_t max_size, unsigned int cpu_mult, gfp_t gfp) | 15 | size_t max_size, unsigned int cpu_mult, gfp_t gfp, |
| 16 | const char *name, struct lock_class_key *key) | ||
| 16 | { | 17 | { |
| 17 | spinlock_t *tlocks = NULL; | 18 | spinlock_t *tlocks = NULL; |
| 18 | unsigned int i, size; | 19 | unsigned int i, size; |
| @@ -33,8 +34,10 @@ int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask, | |||
| 33 | tlocks = kvmalloc_array(size, sizeof(spinlock_t), gfp); | 34 | tlocks = kvmalloc_array(size, sizeof(spinlock_t), gfp); |
| 34 | if (!tlocks) | 35 | if (!tlocks) |
| 35 | return -ENOMEM; | 36 | return -ENOMEM; |
| 36 | for (i = 0; i < size; i++) | 37 | for (i = 0; i < size; i++) { |
| 37 | spin_lock_init(&tlocks[i]); | 38 | spin_lock_init(&tlocks[i]); |
| 39 | lockdep_init_map(&tlocks[i].dep_map, name, key, 0); | ||
| 40 | } | ||
| 38 | } | 41 | } |
| 39 | 42 | ||
| 40 | *locks = tlocks; | 43 | *locks = tlocks; |
| @@ -42,7 +45,7 @@ int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *locks_mask, | |||
| 42 | 45 | ||
| 43 | return 0; | 46 | return 0; |
| 44 | } | 47 | } |
| 45 | EXPORT_SYMBOL(alloc_bucket_spinlocks); | 48 | EXPORT_SYMBOL(__alloc_bucket_spinlocks); |
| 46 | 49 | ||
| 47 | void free_bucket_spinlocks(spinlock_t *locks) | 50 | void free_bucket_spinlocks(spinlock_t *locks) |
| 48 | { | 51 | { |
diff --git a/net/core/filter.c b/net/core/filter.c index fd423ce3da34..c25eb36f1320 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -3246,31 +3246,33 @@ static void *__xdp_map_lookup_elem(struct bpf_map *map, u32 index) | |||
| 3246 | } | 3246 | } |
| 3247 | } | 3247 | } |
| 3248 | 3248 | ||
| 3249 | static inline bool xdp_map_invalid(const struct bpf_prog *xdp_prog, | 3249 | void bpf_clear_redirect_map(struct bpf_map *map) |
| 3250 | unsigned long aux) | ||
| 3251 | { | 3250 | { |
| 3252 | return (unsigned long)xdp_prog->aux != aux; | 3251 | struct bpf_redirect_info *ri; |
| 3252 | int cpu; | ||
| 3253 | |||
| 3254 | for_each_possible_cpu(cpu) { | ||
| 3255 | ri = per_cpu_ptr(&bpf_redirect_info, cpu); | ||
| 3256 | /* Avoid polluting remote cacheline due to writes if | ||
| 3257 | * not needed. Once we pass this test, we need the | ||
| 3258 | * cmpxchg() to make sure it hasn't been changed in | ||
| 3259 | * the meantime by remote CPU. | ||
| 3260 | */ | ||
| 3261 | if (unlikely(READ_ONCE(ri->map) == map)) | ||
| 3262 | cmpxchg(&ri->map, map, NULL); | ||
| 3263 | } | ||
| 3253 | } | 3264 | } |
| 3254 | 3265 | ||
| 3255 | static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp, | 3266 | static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp, |
| 3256 | struct bpf_prog *xdp_prog) | 3267 | struct bpf_prog *xdp_prog, struct bpf_map *map) |
| 3257 | { | 3268 | { |
| 3258 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); | 3269 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); |
| 3259 | unsigned long map_owner = ri->map_owner; | ||
| 3260 | struct bpf_map *map = ri->map; | ||
| 3261 | u32 index = ri->ifindex; | 3270 | u32 index = ri->ifindex; |
| 3262 | void *fwd = NULL; | 3271 | void *fwd = NULL; |
| 3263 | int err; | 3272 | int err; |
| 3264 | 3273 | ||
| 3265 | ri->ifindex = 0; | 3274 | ri->ifindex = 0; |
| 3266 | ri->map = NULL; | 3275 | WRITE_ONCE(ri->map, NULL); |
| 3267 | ri->map_owner = 0; | ||
| 3268 | |||
| 3269 | if (unlikely(xdp_map_invalid(xdp_prog, map_owner))) { | ||
| 3270 | err = -EFAULT; | ||
| 3271 | map = NULL; | ||
| 3272 | goto err; | ||
| 3273 | } | ||
| 3274 | 3276 | ||
| 3275 | fwd = __xdp_map_lookup_elem(map, index); | 3277 | fwd = __xdp_map_lookup_elem(map, index); |
| 3276 | if (!fwd) { | 3278 | if (!fwd) { |
| @@ -3296,12 +3298,13 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp, | |||
| 3296 | struct bpf_prog *xdp_prog) | 3298 | struct bpf_prog *xdp_prog) |
| 3297 | { | 3299 | { |
| 3298 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); | 3300 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); |
| 3301 | struct bpf_map *map = READ_ONCE(ri->map); | ||
| 3299 | struct net_device *fwd; | 3302 | struct net_device *fwd; |
| 3300 | u32 index = ri->ifindex; | 3303 | u32 index = ri->ifindex; |
| 3301 | int err; | 3304 | int err; |
| 3302 | 3305 | ||
| 3303 | if (ri->map) | 3306 | if (map) |
| 3304 | return xdp_do_redirect_map(dev, xdp, xdp_prog); | 3307 | return xdp_do_redirect_map(dev, xdp, xdp_prog, map); |
| 3305 | 3308 | ||
| 3306 | fwd = dev_get_by_index_rcu(dev_net(dev), index); | 3309 | fwd = dev_get_by_index_rcu(dev_net(dev), index); |
| 3307 | ri->ifindex = 0; | 3310 | ri->ifindex = 0; |
| @@ -3325,24 +3328,17 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect); | |||
| 3325 | static int xdp_do_generic_redirect_map(struct net_device *dev, | 3328 | static int xdp_do_generic_redirect_map(struct net_device *dev, |
| 3326 | struct sk_buff *skb, | 3329 | struct sk_buff *skb, |
| 3327 | struct xdp_buff *xdp, | 3330 | struct xdp_buff *xdp, |
| 3328 | struct bpf_prog *xdp_prog) | 3331 | struct bpf_prog *xdp_prog, |
| 3332 | struct bpf_map *map) | ||
| 3329 | { | 3333 | { |
| 3330 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); | 3334 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); |
| 3331 | unsigned long map_owner = ri->map_owner; | ||
| 3332 | struct bpf_map *map = ri->map; | ||
| 3333 | u32 index = ri->ifindex; | 3335 | u32 index = ri->ifindex; |
| 3334 | void *fwd = NULL; | 3336 | void *fwd = NULL; |
| 3335 | int err = 0; | 3337 | int err = 0; |
| 3336 | 3338 | ||
| 3337 | ri->ifindex = 0; | 3339 | ri->ifindex = 0; |
| 3338 | ri->map = NULL; | 3340 | WRITE_ONCE(ri->map, NULL); |
| 3339 | ri->map_owner = 0; | ||
| 3340 | 3341 | ||
| 3341 | if (unlikely(xdp_map_invalid(xdp_prog, map_owner))) { | ||
| 3342 | err = -EFAULT; | ||
| 3343 | map = NULL; | ||
| 3344 | goto err; | ||
| 3345 | } | ||
| 3346 | fwd = __xdp_map_lookup_elem(map, index); | 3342 | fwd = __xdp_map_lookup_elem(map, index); |
| 3347 | if (unlikely(!fwd)) { | 3343 | if (unlikely(!fwd)) { |
| 3348 | err = -EINVAL; | 3344 | err = -EINVAL; |
| @@ -3379,13 +3375,14 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb, | |||
| 3379 | struct xdp_buff *xdp, struct bpf_prog *xdp_prog) | 3375 | struct xdp_buff *xdp, struct bpf_prog *xdp_prog) |
| 3380 | { | 3376 | { |
| 3381 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); | 3377 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); |
| 3378 | struct bpf_map *map = READ_ONCE(ri->map); | ||
| 3382 | u32 index = ri->ifindex; | 3379 | u32 index = ri->ifindex; |
| 3383 | struct net_device *fwd; | 3380 | struct net_device *fwd; |
| 3384 | int err = 0; | 3381 | int err = 0; |
| 3385 | 3382 | ||
| 3386 | if (ri->map) | 3383 | if (map) |
| 3387 | return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog); | 3384 | return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, |
| 3388 | 3385 | map); | |
| 3389 | ri->ifindex = 0; | 3386 | ri->ifindex = 0; |
| 3390 | fwd = dev_get_by_index_rcu(dev_net(dev), index); | 3387 | fwd = dev_get_by_index_rcu(dev_net(dev), index); |
| 3391 | if (unlikely(!fwd)) { | 3388 | if (unlikely(!fwd)) { |
| @@ -3416,8 +3413,7 @@ BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags) | |||
| 3416 | 3413 | ||
| 3417 | ri->ifindex = ifindex; | 3414 | ri->ifindex = ifindex; |
| 3418 | ri->flags = flags; | 3415 | ri->flags = flags; |
| 3419 | ri->map = NULL; | 3416 | WRITE_ONCE(ri->map, NULL); |
| 3420 | ri->map_owner = 0; | ||
| 3421 | 3417 | ||
| 3422 | return XDP_REDIRECT; | 3418 | return XDP_REDIRECT; |
| 3423 | } | 3419 | } |
| @@ -3430,8 +3426,8 @@ static const struct bpf_func_proto bpf_xdp_redirect_proto = { | |||
| 3430 | .arg2_type = ARG_ANYTHING, | 3426 | .arg2_type = ARG_ANYTHING, |
| 3431 | }; | 3427 | }; |
| 3432 | 3428 | ||
| 3433 | BPF_CALL_4(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags, | 3429 | BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, |
| 3434 | unsigned long, map_owner) | 3430 | u64, flags) |
| 3435 | { | 3431 | { |
| 3436 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); | 3432 | struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info); |
| 3437 | 3433 | ||
| @@ -3440,15 +3436,11 @@ BPF_CALL_4(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags | |||
| 3440 | 3436 | ||
| 3441 | ri->ifindex = ifindex; | 3437 | ri->ifindex = ifindex; |
| 3442 | ri->flags = flags; | 3438 | ri->flags = flags; |
| 3443 | ri->map = map; | 3439 | WRITE_ONCE(ri->map, map); |
| 3444 | ri->map_owner = map_owner; | ||
| 3445 | 3440 | ||
| 3446 | return XDP_REDIRECT; | 3441 | return XDP_REDIRECT; |
| 3447 | } | 3442 | } |
| 3448 | 3443 | ||
| 3449 | /* Note, arg4 is hidden from users and populated by the verifier | ||
| 3450 | * with the right pointer. | ||
| 3451 | */ | ||
| 3452 | static const struct bpf_func_proto bpf_xdp_redirect_map_proto = { | 3444 | static const struct bpf_func_proto bpf_xdp_redirect_map_proto = { |
| 3453 | .func = bpf_xdp_redirect_map, | 3445 | .func = bpf_xdp_redirect_map, |
| 3454 | .gpl_only = false, | 3446 | .gpl_only = false, |
diff --git a/net/core/xdp.c b/net/core/xdp.c index 3dd99e1c04f5..89b6785cef2a 100644 --- a/net/core/xdp.c +++ b/net/core/xdp.c | |||
| @@ -98,23 +98,15 @@ static void __xdp_rxq_info_unreg_mem_model(struct xdp_rxq_info *xdp_rxq) | |||
| 98 | { | 98 | { |
| 99 | struct xdp_mem_allocator *xa; | 99 | struct xdp_mem_allocator *xa; |
| 100 | int id = xdp_rxq->mem.id; | 100 | int id = xdp_rxq->mem.id; |
| 101 | int err; | ||
| 102 | 101 | ||
| 103 | if (id == 0) | 102 | if (id == 0) |
| 104 | return; | 103 | return; |
| 105 | 104 | ||
| 106 | mutex_lock(&mem_id_lock); | 105 | mutex_lock(&mem_id_lock); |
| 107 | 106 | ||
| 108 | xa = rhashtable_lookup(mem_id_ht, &id, mem_id_rht_params); | 107 | xa = rhashtable_lookup_fast(mem_id_ht, &id, mem_id_rht_params); |
| 109 | if (!xa) { | 108 | if (xa && !rhashtable_remove_fast(mem_id_ht, &xa->node, mem_id_rht_params)) |
| 110 | mutex_unlock(&mem_id_lock); | 109 | call_rcu(&xa->rcu, __xdp_mem_allocator_rcu_free); |
| 111 | return; | ||
| 112 | } | ||
| 113 | |||
| 114 | err = rhashtable_remove_fast(mem_id_ht, &xa->node, mem_id_rht_params); | ||
| 115 | WARN_ON(err); | ||
| 116 | |||
| 117 | call_rcu(&xa->rcu, __xdp_mem_allocator_rcu_free); | ||
| 118 | 110 | ||
| 119 | mutex_unlock(&mem_id_lock); | 111 | mutex_unlock(&mem_id_lock); |
| 120 | } | 112 | } |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 3f091ccad9af..f38cb21d773d 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
| @@ -438,7 +438,8 @@ static int __net_init vti_init_net(struct net *net) | |||
| 438 | if (err) | 438 | if (err) |
| 439 | return err; | 439 | return err; |
| 440 | itn = net_generic(net, vti_net_id); | 440 | itn = net_generic(net, vti_net_id); |
| 441 | vti_fb_tunnel_init(itn->fb_tunnel_dev); | 441 | if (itn->fb_tunnel_dev) |
| 442 | vti_fb_tunnel_init(itn->fb_tunnel_dev); | ||
| 442 | return 0; | 443 | return 0; |
| 443 | } | 444 | } |
| 444 | 445 | ||
diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c index 622caa4039e0..a5995bb2eaca 100644 --- a/net/ipv4/tcp_ulp.c +++ b/net/ipv4/tcp_ulp.c | |||
| @@ -51,7 +51,7 @@ static const struct tcp_ulp_ops *__tcp_ulp_find_autoload(const char *name) | |||
| 51 | #ifdef CONFIG_MODULES | 51 | #ifdef CONFIG_MODULES |
| 52 | if (!ulp && capable(CAP_NET_ADMIN)) { | 52 | if (!ulp && capable(CAP_NET_ADMIN)) { |
| 53 | rcu_read_unlock(); | 53 | rcu_read_unlock(); |
| 54 | request_module("%s", name); | 54 | request_module("tcp-ulp-%s", name); |
| 55 | rcu_read_lock(); | 55 | rcu_read_lock(); |
| 56 | ulp = tcp_ulp_find(name); | 56 | ulp = tcp_ulp_find(name); |
| 57 | } | 57 | } |
| @@ -129,6 +129,8 @@ void tcp_cleanup_ulp(struct sock *sk) | |||
| 129 | if (icsk->icsk_ulp_ops->release) | 129 | if (icsk->icsk_ulp_ops->release) |
| 130 | icsk->icsk_ulp_ops->release(sk); | 130 | icsk->icsk_ulp_ops->release(sk); |
| 131 | module_put(icsk->icsk_ulp_ops->owner); | 131 | module_put(icsk->icsk_ulp_ops->owner); |
| 132 | |||
| 133 | icsk->icsk_ulp_ops = NULL; | ||
| 132 | } | 134 | } |
| 133 | 135 | ||
| 134 | /* Change upper layer protocol for socket */ | 136 | /* Change upper layer protocol for socket */ |
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index c72ae3a4fe09..38dec9da90d3 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
| @@ -503,17 +503,9 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) | |||
| 503 | skb->dev = skb_dst(skb)->dev; | 503 | skb->dev = skb_dst(skb)->dev; |
| 504 | 504 | ||
| 505 | err = dst_output(t->net, skb->sk, skb); | 505 | err = dst_output(t->net, skb->sk, skb); |
| 506 | if (net_xmit_eval(err) == 0) { | 506 | if (net_xmit_eval(err) == 0) |
| 507 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); | 507 | err = pkt_len; |
| 508 | 508 | iptunnel_xmit_stats(dev, err); | |
| 509 | u64_stats_update_begin(&tstats->syncp); | ||
| 510 | tstats->tx_bytes += pkt_len; | ||
| 511 | tstats->tx_packets++; | ||
| 512 | u64_stats_update_end(&tstats->syncp); | ||
| 513 | } else { | ||
| 514 | stats->tx_errors++; | ||
| 515 | stats->tx_aborted_errors++; | ||
| 516 | } | ||
| 517 | 509 | ||
| 518 | return 0; | 510 | return 0; |
| 519 | tx_err_link_failure: | 511 | tx_err_link_failure: |
| @@ -1114,6 +1106,8 @@ static int __net_init vti6_init_net(struct net *net) | |||
| 1114 | ip6n->tnls[0] = ip6n->tnls_wc; | 1106 | ip6n->tnls[0] = ip6n->tnls_wc; |
| 1115 | ip6n->tnls[1] = ip6n->tnls_r_l; | 1107 | ip6n->tnls[1] = ip6n->tnls_r_l; |
| 1116 | 1108 | ||
| 1109 | if (!net_has_fallback_tunnels(net)) | ||
| 1110 | return 0; | ||
| 1117 | err = -ENOMEM; | 1111 | err = -ENOMEM; |
| 1118 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6_vti0", | 1112 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6_vti0", |
| 1119 | NET_NAME_UNKNOWN, vti6_dev_setup); | 1113 | NET_NAME_UNKNOWN, vti6_dev_setup); |
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c index 0fe61ede77c6..c3c6b09acdc4 100644 --- a/net/ipv6/netfilter/ip6t_rpfilter.c +++ b/net/ipv6/netfilter/ip6t_rpfilter.c | |||
| @@ -26,6 +26,12 @@ static bool rpfilter_addr_unicast(const struct in6_addr *addr) | |||
| 26 | return addr_type & IPV6_ADDR_UNICAST; | 26 | return addr_type & IPV6_ADDR_UNICAST; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | static bool rpfilter_addr_linklocal(const struct in6_addr *addr) | ||
| 30 | { | ||
| 31 | int addr_type = ipv6_addr_type(addr); | ||
| 32 | return addr_type & IPV6_ADDR_LINKLOCAL; | ||
| 33 | } | ||
| 34 | |||
| 29 | static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb, | 35 | static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb, |
| 30 | const struct net_device *dev, u8 flags) | 36 | const struct net_device *dev, u8 flags) |
| 31 | { | 37 | { |
| @@ -48,7 +54,11 @@ static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb, | |||
| 48 | } | 54 | } |
| 49 | 55 | ||
| 50 | fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; | 56 | fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; |
| 51 | if ((flags & XT_RPFILTER_LOOSE) == 0) | 57 | |
| 58 | if (rpfilter_addr_linklocal(&iph->saddr)) { | ||
| 59 | lookup_flags |= RT6_LOOKUP_F_IFACE; | ||
| 60 | fl6.flowi6_oif = dev->ifindex; | ||
| 61 | } else if ((flags & XT_RPFILTER_LOOSE) == 0) | ||
| 52 | fl6.flowi6_oif = dev->ifindex; | 62 | fl6.flowi6_oif = dev->ifindex; |
| 53 | 63 | ||
| 54 | rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags); | 64 | rt = (void *)ip6_route_lookup(net, &fl6, skb, lookup_flags); |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 0edc62910ebf..5b2b17867cb1 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
| @@ -1117,24 +1117,28 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) | |||
| 1117 | #ifdef CONFIG_IP_VS_IPV6 | 1117 | #ifdef CONFIG_IP_VS_IPV6 |
| 1118 | if (cp->af == AF_INET6) | 1118 | if (cp->af == AF_INET6) |
| 1119 | seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X " | 1119 | seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X " |
| 1120 | "%s %04X %-11s %7lu%s\n", | 1120 | "%s %04X %-11s %7u%s\n", |
| 1121 | ip_vs_proto_name(cp->protocol), | 1121 | ip_vs_proto_name(cp->protocol), |
| 1122 | &cp->caddr.in6, ntohs(cp->cport), | 1122 | &cp->caddr.in6, ntohs(cp->cport), |
| 1123 | &cp->vaddr.in6, ntohs(cp->vport), | 1123 | &cp->vaddr.in6, ntohs(cp->vport), |
| 1124 | dbuf, ntohs(cp->dport), | 1124 | dbuf, ntohs(cp->dport), |
| 1125 | ip_vs_state_name(cp), | 1125 | ip_vs_state_name(cp), |
| 1126 | (cp->timer.expires-jiffies)/HZ, pe_data); | 1126 | jiffies_delta_to_msecs(cp->timer.expires - |
| 1127 | jiffies) / 1000, | ||
| 1128 | pe_data); | ||
| 1127 | else | 1129 | else |
| 1128 | #endif | 1130 | #endif |
| 1129 | seq_printf(seq, | 1131 | seq_printf(seq, |
| 1130 | "%-3s %08X %04X %08X %04X" | 1132 | "%-3s %08X %04X %08X %04X" |
| 1131 | " %s %04X %-11s %7lu%s\n", | 1133 | " %s %04X %-11s %7u%s\n", |
| 1132 | ip_vs_proto_name(cp->protocol), | 1134 | ip_vs_proto_name(cp->protocol), |
| 1133 | ntohl(cp->caddr.ip), ntohs(cp->cport), | 1135 | ntohl(cp->caddr.ip), ntohs(cp->cport), |
| 1134 | ntohl(cp->vaddr.ip), ntohs(cp->vport), | 1136 | ntohl(cp->vaddr.ip), ntohs(cp->vport), |
| 1135 | dbuf, ntohs(cp->dport), | 1137 | dbuf, ntohs(cp->dport), |
| 1136 | ip_vs_state_name(cp), | 1138 | ip_vs_state_name(cp), |
| 1137 | (cp->timer.expires-jiffies)/HZ, pe_data); | 1139 | jiffies_delta_to_msecs(cp->timer.expires - |
| 1140 | jiffies) / 1000, | ||
| 1141 | pe_data); | ||
| 1138 | } | 1142 | } |
| 1139 | return 0; | 1143 | return 0; |
| 1140 | } | 1144 | } |
| @@ -1179,26 +1183,28 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) | |||
| 1179 | #ifdef CONFIG_IP_VS_IPV6 | 1183 | #ifdef CONFIG_IP_VS_IPV6 |
| 1180 | if (cp->af == AF_INET6) | 1184 | if (cp->af == AF_INET6) |
| 1181 | seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X " | 1185 | seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X " |
| 1182 | "%s %04X %-11s %-6s %7lu\n", | 1186 | "%s %04X %-11s %-6s %7u\n", |
| 1183 | ip_vs_proto_name(cp->protocol), | 1187 | ip_vs_proto_name(cp->protocol), |
| 1184 | &cp->caddr.in6, ntohs(cp->cport), | 1188 | &cp->caddr.in6, ntohs(cp->cport), |
| 1185 | &cp->vaddr.in6, ntohs(cp->vport), | 1189 | &cp->vaddr.in6, ntohs(cp->vport), |
| 1186 | dbuf, ntohs(cp->dport), | 1190 | dbuf, ntohs(cp->dport), |
| 1187 | ip_vs_state_name(cp), | 1191 | ip_vs_state_name(cp), |
| 1188 | ip_vs_origin_name(cp->flags), | 1192 | ip_vs_origin_name(cp->flags), |
| 1189 | (cp->timer.expires-jiffies)/HZ); | 1193 | jiffies_delta_to_msecs(cp->timer.expires - |
| 1194 | jiffies) / 1000); | ||
| 1190 | else | 1195 | else |
| 1191 | #endif | 1196 | #endif |
| 1192 | seq_printf(seq, | 1197 | seq_printf(seq, |
| 1193 | "%-3s %08X %04X %08X %04X " | 1198 | "%-3s %08X %04X %08X %04X " |
| 1194 | "%s %04X %-11s %-6s %7lu\n", | 1199 | "%s %04X %-11s %-6s %7u\n", |
| 1195 | ip_vs_proto_name(cp->protocol), | 1200 | ip_vs_proto_name(cp->protocol), |
| 1196 | ntohl(cp->caddr.ip), ntohs(cp->cport), | 1201 | ntohl(cp->caddr.ip), ntohs(cp->cport), |
| 1197 | ntohl(cp->vaddr.ip), ntohs(cp->vport), | 1202 | ntohl(cp->vaddr.ip), ntohs(cp->vport), |
| 1198 | dbuf, ntohs(cp->dport), | 1203 | dbuf, ntohs(cp->dport), |
| 1199 | ip_vs_state_name(cp), | 1204 | ip_vs_state_name(cp), |
| 1200 | ip_vs_origin_name(cp->flags), | 1205 | ip_vs_origin_name(cp->flags), |
| 1201 | (cp->timer.expires-jiffies)/HZ); | 1206 | jiffies_delta_to_msecs(cp->timer.expires - |
| 1207 | jiffies) / 1000); | ||
| 1202 | } | 1208 | } |
| 1203 | return 0; | 1209 | return 0; |
| 1204 | } | 1210 | } |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 0679dd101e72..7ca926a03b81 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -1972,13 +1972,20 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int | |||
| 1972 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { | 1972 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
| 1973 | /* the destination server is not available */ | 1973 | /* the destination server is not available */ |
| 1974 | 1974 | ||
| 1975 | if (sysctl_expire_nodest_conn(ipvs)) { | 1975 | __u32 flags = cp->flags; |
| 1976 | |||
| 1977 | /* when timer already started, silently drop the packet.*/ | ||
| 1978 | if (timer_pending(&cp->timer)) | ||
| 1979 | __ip_vs_conn_put(cp); | ||
| 1980 | else | ||
| 1981 | ip_vs_conn_put(cp); | ||
| 1982 | |||
| 1983 | if (sysctl_expire_nodest_conn(ipvs) && | ||
| 1984 | !(flags & IP_VS_CONN_F_ONE_PACKET)) { | ||
| 1976 | /* try to expire the connection immediately */ | 1985 | /* try to expire the connection immediately */ |
| 1977 | ip_vs_conn_expire_now(cp); | 1986 | ip_vs_conn_expire_now(cp); |
| 1978 | } | 1987 | } |
| 1979 | /* don't restart its timer, and silently | 1988 | |
| 1980 | drop the packet. */ | ||
| 1981 | __ip_vs_conn_put(cp); | ||
| 1982 | return NF_DROP; | 1989 | return NF_DROP; |
| 1983 | } | 1990 | } |
| 1984 | 1991 | ||
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index f981bfa8db72..036207ecaf16 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -846,6 +846,21 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[]) | |||
| 846 | #endif | 846 | #endif |
| 847 | } | 847 | } |
| 848 | 848 | ||
| 849 | static int ctnetlink_start(struct netlink_callback *cb) | ||
| 850 | { | ||
| 851 | const struct nlattr * const *cda = cb->data; | ||
| 852 | struct ctnetlink_filter *filter = NULL; | ||
| 853 | |||
| 854 | if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) { | ||
| 855 | filter = ctnetlink_alloc_filter(cda); | ||
| 856 | if (IS_ERR(filter)) | ||
| 857 | return PTR_ERR(filter); | ||
| 858 | } | ||
| 859 | |||
| 860 | cb->data = filter; | ||
| 861 | return 0; | ||
| 862 | } | ||
| 863 | |||
| 849 | static int ctnetlink_filter_match(struct nf_conn *ct, void *data) | 864 | static int ctnetlink_filter_match(struct nf_conn *ct, void *data) |
| 850 | { | 865 | { |
| 851 | struct ctnetlink_filter *filter = data; | 866 | struct ctnetlink_filter *filter = data; |
| @@ -1290,19 +1305,12 @@ static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl, | |||
| 1290 | 1305 | ||
| 1291 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 1306 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
| 1292 | struct netlink_dump_control c = { | 1307 | struct netlink_dump_control c = { |
| 1308 | .start = ctnetlink_start, | ||
| 1293 | .dump = ctnetlink_dump_table, | 1309 | .dump = ctnetlink_dump_table, |
| 1294 | .done = ctnetlink_done, | 1310 | .done = ctnetlink_done, |
| 1311 | .data = (void *)cda, | ||
| 1295 | }; | 1312 | }; |
| 1296 | 1313 | ||
| 1297 | if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) { | ||
| 1298 | struct ctnetlink_filter *filter; | ||
| 1299 | |||
| 1300 | filter = ctnetlink_alloc_filter(cda); | ||
| 1301 | if (IS_ERR(filter)) | ||
| 1302 | return PTR_ERR(filter); | ||
| 1303 | |||
| 1304 | c.data = filter; | ||
| 1305 | } | ||
| 1306 | return netlink_dump_start(ctnl, skb, nlh, &c); | 1314 | return netlink_dump_start(ctnl, skb, nlh, &c); |
| 1307 | } | 1315 | } |
| 1308 | 1316 | ||
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 30070732ee50..9f14b0df6960 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
| @@ -312,7 +312,9 @@ void nf_ct_l4proto_unregister_one(const struct nf_conntrack_l4proto *l4proto) | |||
| 312 | __nf_ct_l4proto_unregister_one(l4proto); | 312 | __nf_ct_l4proto_unregister_one(l4proto); |
| 313 | mutex_unlock(&nf_ct_proto_mutex); | 313 | mutex_unlock(&nf_ct_proto_mutex); |
| 314 | 314 | ||
| 315 | synchronize_rcu(); | 315 | synchronize_net(); |
| 316 | /* Remove all contrack entries for this protocol */ | ||
| 317 | nf_ct_iterate_destroy(kill_l4proto, (void *)l4proto); | ||
| 316 | } | 318 | } |
| 317 | EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister_one); | 319 | EXPORT_SYMBOL_GPL(nf_ct_l4proto_unregister_one); |
| 318 | 320 | ||
| @@ -333,14 +335,17 @@ static void | |||
| 333 | nf_ct_l4proto_unregister(const struct nf_conntrack_l4proto * const l4proto[], | 335 | nf_ct_l4proto_unregister(const struct nf_conntrack_l4proto * const l4proto[], |
| 334 | unsigned int num_proto) | 336 | unsigned int num_proto) |
| 335 | { | 337 | { |
| 338 | int i; | ||
| 339 | |||
| 336 | mutex_lock(&nf_ct_proto_mutex); | 340 | mutex_lock(&nf_ct_proto_mutex); |
| 337 | while (num_proto-- != 0) | 341 | for (i = 0; i < num_proto; i++) |
| 338 | __nf_ct_l4proto_unregister_one(l4proto[num_proto]); | 342 | __nf_ct_l4proto_unregister_one(l4proto[i]); |
| 339 | mutex_unlock(&nf_ct_proto_mutex); | 343 | mutex_unlock(&nf_ct_proto_mutex); |
| 340 | 344 | ||
| 341 | synchronize_net(); | 345 | synchronize_net(); |
| 342 | /* Remove all contrack entries for this protocol */ | 346 | |
| 343 | nf_ct_iterate_destroy(kill_l4proto, (void *)l4proto); | 347 | for (i = 0; i < num_proto; i++) |
| 348 | nf_ct_iterate_destroy(kill_l4proto, (void *)l4proto[i]); | ||
| 344 | } | 349 | } |
| 345 | 350 | ||
| 346 | static int | 351 | static int |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 67cdd5c4f4f5..1dca5683f59f 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -3354,7 +3354,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, | |||
| 3354 | struct nft_set *set; | 3354 | struct nft_set *set; |
| 3355 | struct nft_ctx ctx; | 3355 | struct nft_ctx ctx; |
| 3356 | char *name; | 3356 | char *name; |
| 3357 | unsigned int size; | 3357 | u64 size; |
| 3358 | u64 timeout; | 3358 | u64 timeout; |
| 3359 | u32 ktype, dtype, flags, policy, gc_int, objtype; | 3359 | u32 ktype, dtype, flags, policy, gc_int, objtype; |
| 3360 | struct nft_set_desc desc; | 3360 | struct nft_set_desc desc; |
| @@ -5925,10 +5925,7 @@ static int nf_tables_flowtable_event(struct notifier_block *this, | |||
| 5925 | if (event != NETDEV_UNREGISTER) | 5925 | if (event != NETDEV_UNREGISTER) |
| 5926 | return 0; | 5926 | return 0; |
| 5927 | 5927 | ||
| 5928 | net = maybe_get_net(dev_net(dev)); | 5928 | net = dev_net(dev); |
| 5929 | if (!net) | ||
| 5930 | return 0; | ||
| 5931 | |||
| 5932 | mutex_lock(&net->nft.commit_mutex); | 5929 | mutex_lock(&net->nft.commit_mutex); |
| 5933 | list_for_each_entry(table, &net->nft.tables, list) { | 5930 | list_for_each_entry(table, &net->nft.tables, list) { |
| 5934 | list_for_each_entry(flowtable, &table->flowtables, list) { | 5931 | list_for_each_entry(flowtable, &table->flowtables, list) { |
| @@ -5936,7 +5933,7 @@ static int nf_tables_flowtable_event(struct notifier_block *this, | |||
| 5936 | } | 5933 | } |
| 5937 | } | 5934 | } |
| 5938 | mutex_unlock(&net->nft.commit_mutex); | 5935 | mutex_unlock(&net->nft.commit_mutex); |
| 5939 | put_net(net); | 5936 | |
| 5940 | return NOTIFY_DONE; | 5937 | return NOTIFY_DONE; |
| 5941 | } | 5938 | } |
| 5942 | 5939 | ||
| @@ -7273,21 +7270,36 @@ static int __init nf_tables_module_init(void) | |||
| 7273 | { | 7270 | { |
| 7274 | int err; | 7271 | int err; |
| 7275 | 7272 | ||
| 7276 | nft_chain_filter_init(); | 7273 | err = register_pernet_subsys(&nf_tables_net_ops); |
| 7274 | if (err < 0) | ||
| 7275 | return err; | ||
| 7276 | |||
| 7277 | err = nft_chain_filter_init(); | ||
| 7278 | if (err < 0) | ||
| 7279 | goto err1; | ||
| 7277 | 7280 | ||
| 7278 | err = nf_tables_core_module_init(); | 7281 | err = nf_tables_core_module_init(); |
| 7279 | if (err < 0) | 7282 | if (err < 0) |
| 7280 | return err; | 7283 | goto err2; |
| 7281 | 7284 | ||
| 7282 | err = nfnetlink_subsys_register(&nf_tables_subsys); | 7285 | err = register_netdevice_notifier(&nf_tables_flowtable_notifier); |
| 7283 | if (err < 0) | 7286 | if (err < 0) |
| 7284 | goto err; | 7287 | goto err3; |
| 7285 | 7288 | ||
| 7286 | register_netdevice_notifier(&nf_tables_flowtable_notifier); | 7289 | /* must be last */ |
| 7290 | err = nfnetlink_subsys_register(&nf_tables_subsys); | ||
| 7291 | if (err < 0) | ||
| 7292 | goto err4; | ||
| 7287 | 7293 | ||
| 7288 | return register_pernet_subsys(&nf_tables_net_ops); | 7294 | return err; |
| 7289 | err: | 7295 | err4: |
| 7296 | unregister_netdevice_notifier(&nf_tables_flowtable_notifier); | ||
| 7297 | err3: | ||
| 7290 | nf_tables_core_module_exit(); | 7298 | nf_tables_core_module_exit(); |
| 7299 | err2: | ||
| 7300 | nft_chain_filter_fini(); | ||
| 7301 | err1: | ||
| 7302 | unregister_pernet_subsys(&nf_tables_net_ops); | ||
| 7291 | return err; | 7303 | return err; |
| 7292 | } | 7304 | } |
| 7293 | 7305 | ||
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index a0e5adf0b3b6..8fa8bf7c48e6 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c | |||
| @@ -238,29 +238,33 @@ static const struct nla_policy filter_policy[NFACCT_FILTER_MAX + 1] = { | |||
| 238 | [NFACCT_FILTER_VALUE] = { .type = NLA_U32 }, | 238 | [NFACCT_FILTER_VALUE] = { .type = NLA_U32 }, |
| 239 | }; | 239 | }; |
| 240 | 240 | ||
| 241 | static struct nfacct_filter * | 241 | static int nfnl_acct_start(struct netlink_callback *cb) |
| 242 | nfacct_filter_alloc(const struct nlattr * const attr) | ||
| 243 | { | 242 | { |
| 244 | struct nfacct_filter *filter; | 243 | const struct nlattr *const attr = cb->data; |
| 245 | struct nlattr *tb[NFACCT_FILTER_MAX + 1]; | 244 | struct nlattr *tb[NFACCT_FILTER_MAX + 1]; |
| 245 | struct nfacct_filter *filter; | ||
| 246 | int err; | 246 | int err; |
| 247 | 247 | ||
| 248 | if (!attr) | ||
| 249 | return 0; | ||
| 250 | |||
| 248 | err = nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy, | 251 | err = nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy, |
| 249 | NULL); | 252 | NULL); |
| 250 | if (err < 0) | 253 | if (err < 0) |
| 251 | return ERR_PTR(err); | 254 | return err; |
| 252 | 255 | ||
| 253 | if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE]) | 256 | if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE]) |
| 254 | return ERR_PTR(-EINVAL); | 257 | return -EINVAL; |
| 255 | 258 | ||
| 256 | filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL); | 259 | filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL); |
| 257 | if (!filter) | 260 | if (!filter) |
| 258 | return ERR_PTR(-ENOMEM); | 261 | return -ENOMEM; |
| 259 | 262 | ||
| 260 | filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK])); | 263 | filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK])); |
| 261 | filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE])); | 264 | filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE])); |
| 265 | cb->data = filter; | ||
| 262 | 266 | ||
| 263 | return filter; | 267 | return 0; |
| 264 | } | 268 | } |
| 265 | 269 | ||
| 266 | static int nfnl_acct_get(struct net *net, struct sock *nfnl, | 270 | static int nfnl_acct_get(struct net *net, struct sock *nfnl, |
| @@ -275,18 +279,11 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl, | |||
| 275 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 279 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
| 276 | struct netlink_dump_control c = { | 280 | struct netlink_dump_control c = { |
| 277 | .dump = nfnl_acct_dump, | 281 | .dump = nfnl_acct_dump, |
| 282 | .start = nfnl_acct_start, | ||
| 278 | .done = nfnl_acct_done, | 283 | .done = nfnl_acct_done, |
| 284 | .data = (void *)tb[NFACCT_FILTER], | ||
| 279 | }; | 285 | }; |
| 280 | 286 | ||
| 281 | if (tb[NFACCT_FILTER]) { | ||
| 282 | struct nfacct_filter *filter; | ||
| 283 | |||
| 284 | filter = nfacct_filter_alloc(tb[NFACCT_FILTER]); | ||
| 285 | if (IS_ERR(filter)) | ||
| 286 | return PTR_ERR(filter); | ||
| 287 | |||
| 288 | c.data = filter; | ||
| 289 | } | ||
| 290 | return netlink_dump_start(nfnl, skb, nlh, &c); | 287 | return netlink_dump_start(nfnl, skb, nlh, &c); |
| 291 | } | 288 | } |
| 292 | 289 | ||
diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c index ea5b7c4944f6..3fd540b2c6ba 100644 --- a/net/netfilter/nft_chain_filter.c +++ b/net/netfilter/nft_chain_filter.c | |||
| @@ -293,6 +293,13 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev, | |||
| 293 | if (strcmp(basechain->dev_name, dev->name) != 0) | 293 | if (strcmp(basechain->dev_name, dev->name) != 0) |
| 294 | return; | 294 | return; |
| 295 | 295 | ||
| 296 | /* UNREGISTER events are also happpening on netns exit. | ||
| 297 | * | ||
| 298 | * Altough nf_tables core releases all tables/chains, only | ||
| 299 | * this event handler provides guarantee that | ||
| 300 | * basechain.ops->dev is still accessible, so we cannot | ||
| 301 | * skip exiting net namespaces. | ||
| 302 | */ | ||
| 296 | __nft_release_basechain(ctx); | 303 | __nft_release_basechain(ctx); |
| 297 | break; | 304 | break; |
| 298 | case NETDEV_CHANGENAME: | 305 | case NETDEV_CHANGENAME: |
| @@ -318,10 +325,6 @@ static int nf_tables_netdev_event(struct notifier_block *this, | |||
| 318 | event != NETDEV_CHANGENAME) | 325 | event != NETDEV_CHANGENAME) |
| 319 | return NOTIFY_DONE; | 326 | return NOTIFY_DONE; |
| 320 | 327 | ||
| 321 | ctx.net = maybe_get_net(ctx.net); | ||
| 322 | if (!ctx.net) | ||
| 323 | return NOTIFY_DONE; | ||
| 324 | |||
| 325 | mutex_lock(&ctx.net->nft.commit_mutex); | 328 | mutex_lock(&ctx.net->nft.commit_mutex); |
| 326 | list_for_each_entry(table, &ctx.net->nft.tables, list) { | 329 | list_for_each_entry(table, &ctx.net->nft.tables, list) { |
| 327 | if (table->family != NFPROTO_NETDEV) | 330 | if (table->family != NFPROTO_NETDEV) |
| @@ -338,7 +341,6 @@ static int nf_tables_netdev_event(struct notifier_block *this, | |||
| 338 | } | 341 | } |
| 339 | } | 342 | } |
| 340 | mutex_unlock(&ctx.net->nft.commit_mutex); | 343 | mutex_unlock(&ctx.net->nft.commit_mutex); |
| 341 | put_net(ctx.net); | ||
| 342 | 344 | ||
| 343 | return NOTIFY_DONE; | 345 | return NOTIFY_DONE; |
| 344 | } | 346 | } |
| @@ -392,7 +394,7 @@ int __init nft_chain_filter_init(void) | |||
| 392 | return 0; | 394 | return 0; |
| 393 | } | 395 | } |
| 394 | 396 | ||
| 395 | void __exit nft_chain_filter_fini(void) | 397 | void nft_chain_filter_fini(void) |
| 396 | { | 398 | { |
| 397 | nft_chain_filter_bridge_fini(); | 399 | nft_chain_filter_bridge_fini(); |
| 398 | nft_chain_filter_inet_fini(); | 400 | nft_chain_filter_inet_fini(); |
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 4855d4ce1c8f..26a8baebd072 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
| @@ -832,12 +832,13 @@ static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx, | |||
| 832 | __u8 l4num; | 832 | __u8 l4num; |
| 833 | int ret; | 833 | int ret; |
| 834 | 834 | ||
| 835 | if (!tb[NFTA_CT_TIMEOUT_L3PROTO] || | 835 | if (!tb[NFTA_CT_TIMEOUT_L4PROTO] || |
| 836 | !tb[NFTA_CT_TIMEOUT_L4PROTO] || | ||
| 837 | !tb[NFTA_CT_TIMEOUT_DATA]) | 836 | !tb[NFTA_CT_TIMEOUT_DATA]) |
| 838 | return -EINVAL; | 837 | return -EINVAL; |
| 839 | 838 | ||
| 840 | l3num = ntohs(nla_get_be16(tb[NFTA_CT_TIMEOUT_L3PROTO])); | 839 | if (tb[NFTA_CT_TIMEOUT_L3PROTO]) |
| 840 | l3num = ntohs(nla_get_be16(tb[NFTA_CT_TIMEOUT_L3PROTO])); | ||
| 841 | |||
| 841 | l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]); | 842 | l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]); |
| 842 | priv->l4proto = l4num; | 843 | priv->l4proto = l4num; |
| 843 | 844 | ||
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index 81184c244d1a..6e91a37d57f2 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c | |||
| @@ -187,8 +187,6 @@ static int nft_dynset_init(const struct nft_ctx *ctx, | |||
| 187 | if (tb[NFTA_DYNSET_EXPR] != NULL) { | 187 | if (tb[NFTA_DYNSET_EXPR] != NULL) { |
| 188 | if (!(set->flags & NFT_SET_EVAL)) | 188 | if (!(set->flags & NFT_SET_EVAL)) |
| 189 | return -EINVAL; | 189 | return -EINVAL; |
| 190 | if (!nft_set_is_anonymous(set)) | ||
| 191 | return -EOPNOTSUPP; | ||
| 192 | 190 | ||
| 193 | priv->expr = nft_expr_init(ctx, tb[NFTA_DYNSET_EXPR]); | 191 | priv->expr = nft_expr_init(ctx, tb[NFTA_DYNSET_EXPR]); |
| 194 | if (IS_ERR(priv->expr)) | 192 | if (IS_ERR(priv->expr)) |
diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c index 128bc16f52dd..f866bd41e5d2 100644 --- a/net/netfilter/nft_set_bitmap.c +++ b/net/netfilter/nft_set_bitmap.c | |||
| @@ -248,13 +248,13 @@ static inline u32 nft_bitmap_size(u32 klen) | |||
| 248 | return ((2 << ((klen * BITS_PER_BYTE) - 1)) / BITS_PER_BYTE) << 1; | 248 | return ((2 << ((klen * BITS_PER_BYTE) - 1)) / BITS_PER_BYTE) << 1; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | static inline u32 nft_bitmap_total_size(u32 klen) | 251 | static inline u64 nft_bitmap_total_size(u32 klen) |
| 252 | { | 252 | { |
| 253 | return sizeof(struct nft_bitmap) + nft_bitmap_size(klen); | 253 | return sizeof(struct nft_bitmap) + nft_bitmap_size(klen); |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static unsigned int nft_bitmap_privsize(const struct nlattr * const nla[], | 256 | static u64 nft_bitmap_privsize(const struct nlattr * const nla[], |
| 257 | const struct nft_set_desc *desc) | 257 | const struct nft_set_desc *desc) |
| 258 | { | 258 | { |
| 259 | u32 klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN])); | 259 | u32 klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN])); |
| 260 | 260 | ||
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index 90c3e7e6cacb..015124e649cb 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c | |||
| @@ -341,8 +341,8 @@ schedule: | |||
| 341 | nft_set_gc_interval(set)); | 341 | nft_set_gc_interval(set)); |
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | static unsigned int nft_rhash_privsize(const struct nlattr * const nla[], | 344 | static u64 nft_rhash_privsize(const struct nlattr * const nla[], |
| 345 | const struct nft_set_desc *desc) | 345 | const struct nft_set_desc *desc) |
| 346 | { | 346 | { |
| 347 | return sizeof(struct nft_rhash); | 347 | return sizeof(struct nft_rhash); |
| 348 | } | 348 | } |
| @@ -585,8 +585,8 @@ cont: | |||
| 585 | } | 585 | } |
| 586 | } | 586 | } |
| 587 | 587 | ||
| 588 | static unsigned int nft_hash_privsize(const struct nlattr * const nla[], | 588 | static u64 nft_hash_privsize(const struct nlattr * const nla[], |
| 589 | const struct nft_set_desc *desc) | 589 | const struct nft_set_desc *desc) |
| 590 | { | 590 | { |
| 591 | return sizeof(struct nft_hash) + | 591 | return sizeof(struct nft_hash) + |
| 592 | nft_hash_buckets(desc->size) * sizeof(struct hlist_head); | 592 | nft_hash_buckets(desc->size) * sizeof(struct hlist_head); |
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index 9873d734b494..55e2d9215c0d 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c | |||
| @@ -411,8 +411,8 @@ static void nft_rbtree_gc(struct work_struct *work) | |||
| 411 | nft_set_gc_interval(set)); | 411 | nft_set_gc_interval(set)); |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[], | 414 | static u64 nft_rbtree_privsize(const struct nlattr * const nla[], |
| 415 | const struct nft_set_desc *desc) | 415 | const struct nft_set_desc *desc) |
| 416 | { | 416 | { |
| 417 | return sizeof(struct nft_rbtree); | 417 | return sizeof(struct nft_rbtree); |
| 418 | } | 418 | } |
diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c index eff99dffc842..f92a82c73880 100644 --- a/net/netfilter/nft_tproxy.c +++ b/net/netfilter/nft_tproxy.c | |||
| @@ -82,13 +82,15 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr, | |||
| 82 | const struct nft_tproxy *priv = nft_expr_priv(expr); | 82 | const struct nft_tproxy *priv = nft_expr_priv(expr); |
| 83 | struct sk_buff *skb = pkt->skb; | 83 | struct sk_buff *skb = pkt->skb; |
| 84 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 84 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
| 85 | struct in6_addr taddr = {0}; | 85 | struct in6_addr taddr; |
| 86 | int thoff = pkt->xt.thoff; | 86 | int thoff = pkt->xt.thoff; |
| 87 | struct udphdr _hdr, *hp; | 87 | struct udphdr _hdr, *hp; |
| 88 | __be16 tport = 0; | 88 | __be16 tport = 0; |
| 89 | struct sock *sk; | 89 | struct sock *sk; |
| 90 | int l4proto; | 90 | int l4proto; |
| 91 | 91 | ||
| 92 | memset(&taddr, 0, sizeof(taddr)); | ||
| 93 | |||
| 92 | if (!pkt->tprot_set) { | 94 | if (!pkt->tprot_set) { |
| 93 | regs->verdict.code = NFT_BREAK; | 95 | regs->verdict.code = NFT_BREAK; |
| 94 | return; | 96 | return; |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index d0d8397c9588..aecadd471e1d 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
| @@ -1178,12 +1178,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size) | |||
| 1178 | if (sz < sizeof(*info) || sz >= XT_MAX_TABLE_SIZE) | 1178 | if (sz < sizeof(*info) || sz >= XT_MAX_TABLE_SIZE) |
| 1179 | return NULL; | 1179 | return NULL; |
| 1180 | 1180 | ||
| 1181 | /* __GFP_NORETRY is not fully supported by kvmalloc but it should | 1181 | info = kvmalloc(sz, GFP_KERNEL_ACCOUNT); |
| 1182 | * work reasonably well if sz is too large and bail out rather | ||
| 1183 | * than shoot all processes down before realizing there is nothing | ||
| 1184 | * more to reclaim. | ||
| 1185 | */ | ||
| 1186 | info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY); | ||
| 1187 | if (!info) | 1182 | if (!info) |
| 1188 | return NULL; | 1183 | return NULL; |
| 1189 | 1184 | ||
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index 9b30e62805c7..d30b23e42436 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c | |||
| @@ -147,7 +147,7 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act, | |||
| 147 | struct tcf_t tm; | 147 | struct tcf_t tm; |
| 148 | int ret; | 148 | int ret; |
| 149 | 149 | ||
| 150 | spin_lock(&prog->tcf_lock); | 150 | spin_lock_bh(&prog->tcf_lock); |
| 151 | opt.action = prog->tcf_action; | 151 | opt.action = prog->tcf_action; |
| 152 | if (nla_put(skb, TCA_ACT_BPF_PARMS, sizeof(opt), &opt)) | 152 | if (nla_put(skb, TCA_ACT_BPF_PARMS, sizeof(opt), &opt)) |
| 153 | goto nla_put_failure; | 153 | goto nla_put_failure; |
| @@ -164,11 +164,11 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act, | |||
| 164 | TCA_ACT_BPF_PAD)) | 164 | TCA_ACT_BPF_PAD)) |
| 165 | goto nla_put_failure; | 165 | goto nla_put_failure; |
| 166 | 166 | ||
| 167 | spin_unlock(&prog->tcf_lock); | 167 | spin_unlock_bh(&prog->tcf_lock); |
| 168 | return skb->len; | 168 | return skb->len; |
| 169 | 169 | ||
| 170 | nla_put_failure: | 170 | nla_put_failure: |
| 171 | spin_unlock(&prog->tcf_lock); | 171 | spin_unlock_bh(&prog->tcf_lock); |
| 172 | nlmsg_trim(skb, tp); | 172 | nlmsg_trim(skb, tp); |
| 173 | return -1; | 173 | return -1; |
| 174 | } | 174 | } |
| @@ -340,7 +340,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 340 | 340 | ||
| 341 | prog = to_bpf(*act); | 341 | prog = to_bpf(*act); |
| 342 | 342 | ||
| 343 | spin_lock(&prog->tcf_lock); | 343 | spin_lock_bh(&prog->tcf_lock); |
| 344 | if (res != ACT_P_CREATED) | 344 | if (res != ACT_P_CREATED) |
| 345 | tcf_bpf_prog_fill_cfg(prog, &old); | 345 | tcf_bpf_prog_fill_cfg(prog, &old); |
| 346 | 346 | ||
| @@ -352,7 +352,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 352 | 352 | ||
| 353 | prog->tcf_action = parm->action; | 353 | prog->tcf_action = parm->action; |
| 354 | rcu_assign_pointer(prog->filter, cfg.filter); | 354 | rcu_assign_pointer(prog->filter, cfg.filter); |
| 355 | spin_unlock(&prog->tcf_lock); | 355 | spin_unlock_bh(&prog->tcf_lock); |
| 356 | 356 | ||
| 357 | if (res == ACT_P_CREATED) { | 357 | if (res == ACT_P_CREATED) { |
| 358 | tcf_idr_insert(tn, *act); | 358 | tcf_idr_insert(tn, *act); |
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index 5596fae4e478..e698d3fe2080 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c | |||
| @@ -96,11 +96,11 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, | |||
| 96 | } | 96 | } |
| 97 | params_new->update_flags = parm->update_flags; | 97 | params_new->update_flags = parm->update_flags; |
| 98 | 98 | ||
| 99 | spin_lock(&p->tcf_lock); | 99 | spin_lock_bh(&p->tcf_lock); |
| 100 | p->tcf_action = parm->action; | 100 | p->tcf_action = parm->action; |
| 101 | rcu_swap_protected(p->params, params_new, | 101 | rcu_swap_protected(p->params, params_new, |
| 102 | lockdep_is_held(&p->tcf_lock)); | 102 | lockdep_is_held(&p->tcf_lock)); |
| 103 | spin_unlock(&p->tcf_lock); | 103 | spin_unlock_bh(&p->tcf_lock); |
| 104 | 104 | ||
| 105 | if (params_new) | 105 | if (params_new) |
| 106 | kfree_rcu(params_new, rcu); | 106 | kfree_rcu(params_new, rcu); |
| @@ -604,7 +604,7 @@ static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind, | |||
| 604 | }; | 604 | }; |
| 605 | struct tcf_t t; | 605 | struct tcf_t t; |
| 606 | 606 | ||
| 607 | spin_lock(&p->tcf_lock); | 607 | spin_lock_bh(&p->tcf_lock); |
| 608 | params = rcu_dereference_protected(p->params, | 608 | params = rcu_dereference_protected(p->params, |
| 609 | lockdep_is_held(&p->tcf_lock)); | 609 | lockdep_is_held(&p->tcf_lock)); |
| 610 | opt.action = p->tcf_action; | 610 | opt.action = p->tcf_action; |
| @@ -616,12 +616,12 @@ static int tcf_csum_dump(struct sk_buff *skb, struct tc_action *a, int bind, | |||
| 616 | tcf_tm_dump(&t, &p->tcf_tm); | 616 | tcf_tm_dump(&t, &p->tcf_tm); |
| 617 | if (nla_put_64bit(skb, TCA_CSUM_TM, sizeof(t), &t, TCA_CSUM_PAD)) | 617 | if (nla_put_64bit(skb, TCA_CSUM_TM, sizeof(t), &t, TCA_CSUM_PAD)) |
| 618 | goto nla_put_failure; | 618 | goto nla_put_failure; |
| 619 | spin_unlock(&p->tcf_lock); | 619 | spin_unlock_bh(&p->tcf_lock); |
| 620 | 620 | ||
| 621 | return skb->len; | 621 | return skb->len; |
| 622 | 622 | ||
| 623 | nla_put_failure: | 623 | nla_put_failure: |
| 624 | spin_unlock(&p->tcf_lock); | 624 | spin_unlock_bh(&p->tcf_lock); |
| 625 | nlmsg_trim(skb, b); | 625 | nlmsg_trim(skb, b); |
| 626 | return -1; | 626 | return -1; |
| 627 | } | 627 | } |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index 52a3e474d822..6a3f25a8ffb3 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
| @@ -113,7 +113,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 113 | 113 | ||
| 114 | gact = to_gact(*a); | 114 | gact = to_gact(*a); |
| 115 | 115 | ||
| 116 | spin_lock(&gact->tcf_lock); | 116 | spin_lock_bh(&gact->tcf_lock); |
| 117 | gact->tcf_action = parm->action; | 117 | gact->tcf_action = parm->action; |
| 118 | #ifdef CONFIG_GACT_PROB | 118 | #ifdef CONFIG_GACT_PROB |
| 119 | if (p_parm) { | 119 | if (p_parm) { |
| @@ -126,7 +126,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 126 | gact->tcfg_ptype = p_parm->ptype; | 126 | gact->tcfg_ptype = p_parm->ptype; |
| 127 | } | 127 | } |
| 128 | #endif | 128 | #endif |
| 129 | spin_unlock(&gact->tcf_lock); | 129 | spin_unlock_bh(&gact->tcf_lock); |
| 130 | 130 | ||
| 131 | if (ret == ACT_P_CREATED) | 131 | if (ret == ACT_P_CREATED) |
| 132 | tcf_idr_insert(tn, *a); | 132 | tcf_idr_insert(tn, *a); |
| @@ -183,7 +183,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 183 | }; | 183 | }; |
| 184 | struct tcf_t t; | 184 | struct tcf_t t; |
| 185 | 185 | ||
| 186 | spin_lock(&gact->tcf_lock); | 186 | spin_lock_bh(&gact->tcf_lock); |
| 187 | opt.action = gact->tcf_action; | 187 | opt.action = gact->tcf_action; |
| 188 | if (nla_put(skb, TCA_GACT_PARMS, sizeof(opt), &opt)) | 188 | if (nla_put(skb, TCA_GACT_PARMS, sizeof(opt), &opt)) |
| 189 | goto nla_put_failure; | 189 | goto nla_put_failure; |
| @@ -202,12 +202,12 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 202 | tcf_tm_dump(&t, &gact->tcf_tm); | 202 | tcf_tm_dump(&t, &gact->tcf_tm); |
| 203 | if (nla_put_64bit(skb, TCA_GACT_TM, sizeof(t), &t, TCA_GACT_PAD)) | 203 | if (nla_put_64bit(skb, TCA_GACT_TM, sizeof(t), &t, TCA_GACT_PAD)) |
| 204 | goto nla_put_failure; | 204 | goto nla_put_failure; |
| 205 | spin_unlock(&gact->tcf_lock); | 205 | spin_unlock_bh(&gact->tcf_lock); |
| 206 | 206 | ||
| 207 | return skb->len; | 207 | return skb->len; |
| 208 | 208 | ||
| 209 | nla_put_failure: | 209 | nla_put_failure: |
| 210 | spin_unlock(&gact->tcf_lock); | 210 | spin_unlock_bh(&gact->tcf_lock); |
| 211 | nlmsg_trim(skb, b); | 211 | nlmsg_trim(skb, b); |
| 212 | return -1; | 212 | return -1; |
| 213 | } | 213 | } |
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index fdb928ca81bb..d1081bdf1bdb 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c | |||
| @@ -551,9 +551,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, | |||
| 551 | NULL, NULL); | 551 | NULL, NULL); |
| 552 | if (err) { | 552 | if (err) { |
| 553 | metadata_parse_err: | 553 | metadata_parse_err: |
| 554 | if (ret == ACT_P_CREATED) | ||
| 555 | tcf_idr_release(*a, bind); | ||
| 556 | |||
| 557 | if (exists) | 554 | if (exists) |
| 558 | spin_unlock_bh(&ife->tcf_lock); | 555 | spin_unlock_bh(&ife->tcf_lock); |
| 559 | tcf_idr_release(*a, bind); | 556 | tcf_idr_release(*a, bind); |
| @@ -574,11 +571,10 @@ metadata_parse_err: | |||
| 574 | */ | 571 | */ |
| 575 | err = use_all_metadata(ife); | 572 | err = use_all_metadata(ife); |
| 576 | if (err) { | 573 | if (err) { |
| 577 | if (ret == ACT_P_CREATED) | ||
| 578 | tcf_idr_release(*a, bind); | ||
| 579 | |||
| 580 | if (exists) | 574 | if (exists) |
| 581 | spin_unlock_bh(&ife->tcf_lock); | 575 | spin_unlock_bh(&ife->tcf_lock); |
| 576 | tcf_idr_release(*a, bind); | ||
| 577 | |||
| 582 | kfree(p); | 578 | kfree(p); |
| 583 | return err; | 579 | return err; |
| 584 | } | 580 | } |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 8ec216001077..38fd20f10f67 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
| @@ -159,14 +159,14 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 159 | } | 159 | } |
| 160 | m = to_mirred(*a); | 160 | m = to_mirred(*a); |
| 161 | 161 | ||
| 162 | spin_lock(&m->tcf_lock); | 162 | spin_lock_bh(&m->tcf_lock); |
| 163 | m->tcf_action = parm->action; | 163 | m->tcf_action = parm->action; |
| 164 | m->tcfm_eaction = parm->eaction; | 164 | m->tcfm_eaction = parm->eaction; |
| 165 | 165 | ||
| 166 | if (parm->ifindex) { | 166 | if (parm->ifindex) { |
| 167 | dev = dev_get_by_index(net, parm->ifindex); | 167 | dev = dev_get_by_index(net, parm->ifindex); |
| 168 | if (!dev) { | 168 | if (!dev) { |
| 169 | spin_unlock(&m->tcf_lock); | 169 | spin_unlock_bh(&m->tcf_lock); |
| 170 | tcf_idr_release(*a, bind); | 170 | tcf_idr_release(*a, bind); |
| 171 | return -ENODEV; | 171 | return -ENODEV; |
| 172 | } | 172 | } |
| @@ -177,7 +177,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 177 | dev_put(dev); | 177 | dev_put(dev); |
| 178 | m->tcfm_mac_header_xmit = mac_header_xmit; | 178 | m->tcfm_mac_header_xmit = mac_header_xmit; |
| 179 | } | 179 | } |
| 180 | spin_unlock(&m->tcf_lock); | 180 | spin_unlock_bh(&m->tcf_lock); |
| 181 | 181 | ||
| 182 | if (ret == ACT_P_CREATED) { | 182 | if (ret == ACT_P_CREATED) { |
| 183 | spin_lock(&mirred_list_lock); | 183 | spin_lock(&mirred_list_lock); |
| @@ -305,7 +305,7 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, | |||
| 305 | struct net_device *dev; | 305 | struct net_device *dev; |
| 306 | struct tcf_t t; | 306 | struct tcf_t t; |
| 307 | 307 | ||
| 308 | spin_lock(&m->tcf_lock); | 308 | spin_lock_bh(&m->tcf_lock); |
| 309 | opt.action = m->tcf_action; | 309 | opt.action = m->tcf_action; |
| 310 | opt.eaction = m->tcfm_eaction; | 310 | opt.eaction = m->tcfm_eaction; |
| 311 | dev = tcf_mirred_dev_dereference(m); | 311 | dev = tcf_mirred_dev_dereference(m); |
| @@ -318,12 +318,12 @@ static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, | |||
| 318 | tcf_tm_dump(&t, &m->tcf_tm); | 318 | tcf_tm_dump(&t, &m->tcf_tm); |
| 319 | if (nla_put_64bit(skb, TCA_MIRRED_TM, sizeof(t), &t, TCA_MIRRED_PAD)) | 319 | if (nla_put_64bit(skb, TCA_MIRRED_TM, sizeof(t), &t, TCA_MIRRED_PAD)) |
| 320 | goto nla_put_failure; | 320 | goto nla_put_failure; |
| 321 | spin_unlock(&m->tcf_lock); | 321 | spin_unlock_bh(&m->tcf_lock); |
| 322 | 322 | ||
| 323 | return skb->len; | 323 | return skb->len; |
| 324 | 324 | ||
| 325 | nla_put_failure: | 325 | nla_put_failure: |
| 326 | spin_unlock(&m->tcf_lock); | 326 | spin_unlock_bh(&m->tcf_lock); |
| 327 | nlmsg_trim(skb, b); | 327 | nlmsg_trim(skb, b); |
| 328 | return -1; | 328 | return -1; |
| 329 | } | 329 | } |
| @@ -356,7 +356,7 @@ static int mirred_device_event(struct notifier_block *unused, | |||
| 356 | if (event == NETDEV_UNREGISTER) { | 356 | if (event == NETDEV_UNREGISTER) { |
| 357 | spin_lock(&mirred_list_lock); | 357 | spin_lock(&mirred_list_lock); |
| 358 | list_for_each_entry(m, &mirred_list, tcfm_list) { | 358 | list_for_each_entry(m, &mirred_list, tcfm_list) { |
| 359 | spin_lock(&m->tcf_lock); | 359 | spin_lock_bh(&m->tcf_lock); |
| 360 | if (tcf_mirred_dev_dereference(m) == dev) { | 360 | if (tcf_mirred_dev_dereference(m) == dev) { |
| 361 | dev_put(dev); | 361 | dev_put(dev); |
| 362 | /* Note : no rcu grace period necessary, as | 362 | /* Note : no rcu grace period necessary, as |
| @@ -364,7 +364,7 @@ static int mirred_device_event(struct notifier_block *unused, | |||
| 364 | */ | 364 | */ |
| 365 | RCU_INIT_POINTER(m->tcfm_dev, NULL); | 365 | RCU_INIT_POINTER(m->tcfm_dev, NULL); |
| 366 | } | 366 | } |
| 367 | spin_unlock(&m->tcf_lock); | 367 | spin_unlock_bh(&m->tcf_lock); |
| 368 | } | 368 | } |
| 369 | spin_unlock(&mirred_list_lock); | 369 | spin_unlock(&mirred_list_lock); |
| 370 | } | 370 | } |
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c index 81071afe1b43..207b4132d1b0 100644 --- a/net/sched/act_sample.c +++ b/net/sched/act_sample.c | |||
| @@ -44,6 +44,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 44 | struct nlattr *tb[TCA_SAMPLE_MAX + 1]; | 44 | struct nlattr *tb[TCA_SAMPLE_MAX + 1]; |
| 45 | struct psample_group *psample_group; | 45 | struct psample_group *psample_group; |
| 46 | struct tc_sample *parm; | 46 | struct tc_sample *parm; |
| 47 | u32 psample_group_num; | ||
| 47 | struct tcf_sample *s; | 48 | struct tcf_sample *s; |
| 48 | bool exists = false; | 49 | bool exists = false; |
| 49 | int ret, err; | 50 | int ret, err; |
| @@ -78,25 +79,27 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 78 | tcf_idr_release(*a, bind); | 79 | tcf_idr_release(*a, bind); |
| 79 | return -EEXIST; | 80 | return -EEXIST; |
| 80 | } | 81 | } |
| 81 | s = to_sample(*a); | ||
| 82 | 82 | ||
| 83 | spin_lock(&s->tcf_lock); | 83 | psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]); |
| 84 | s->tcf_action = parm->action; | 84 | psample_group = psample_group_get(net, psample_group_num); |
| 85 | s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]); | ||
| 86 | s->psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]); | ||
| 87 | psample_group = psample_group_get(net, s->psample_group_num); | ||
| 88 | if (!psample_group) { | 85 | if (!psample_group) { |
| 89 | spin_unlock(&s->tcf_lock); | ||
| 90 | tcf_idr_release(*a, bind); | 86 | tcf_idr_release(*a, bind); |
| 91 | return -ENOMEM; | 87 | return -ENOMEM; |
| 92 | } | 88 | } |
| 89 | |||
| 90 | s = to_sample(*a); | ||
| 91 | |||
| 92 | spin_lock_bh(&s->tcf_lock); | ||
| 93 | s->tcf_action = parm->action; | ||
| 94 | s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]); | ||
| 95 | s->psample_group_num = psample_group_num; | ||
| 93 | RCU_INIT_POINTER(s->psample_group, psample_group); | 96 | RCU_INIT_POINTER(s->psample_group, psample_group); |
| 94 | 97 | ||
| 95 | if (tb[TCA_SAMPLE_TRUNC_SIZE]) { | 98 | if (tb[TCA_SAMPLE_TRUNC_SIZE]) { |
| 96 | s->truncate = true; | 99 | s->truncate = true; |
| 97 | s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]); | 100 | s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]); |
| 98 | } | 101 | } |
| 99 | spin_unlock(&s->tcf_lock); | 102 | spin_unlock_bh(&s->tcf_lock); |
| 100 | 103 | ||
| 101 | if (ret == ACT_P_CREATED) | 104 | if (ret == ACT_P_CREATED) |
| 102 | tcf_idr_insert(tn, *a); | 105 | tcf_idr_insert(tn, *a); |
| @@ -183,7 +186,7 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 183 | }; | 186 | }; |
| 184 | struct tcf_t t; | 187 | struct tcf_t t; |
| 185 | 188 | ||
| 186 | spin_lock(&s->tcf_lock); | 189 | spin_lock_bh(&s->tcf_lock); |
| 187 | opt.action = s->tcf_action; | 190 | opt.action = s->tcf_action; |
| 188 | if (nla_put(skb, TCA_SAMPLE_PARMS, sizeof(opt), &opt)) | 191 | if (nla_put(skb, TCA_SAMPLE_PARMS, sizeof(opt), &opt)) |
| 189 | goto nla_put_failure; | 192 | goto nla_put_failure; |
| @@ -201,12 +204,12 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 201 | 204 | ||
| 202 | if (nla_put_u32(skb, TCA_SAMPLE_PSAMPLE_GROUP, s->psample_group_num)) | 205 | if (nla_put_u32(skb, TCA_SAMPLE_PSAMPLE_GROUP, s->psample_group_num)) |
| 203 | goto nla_put_failure; | 206 | goto nla_put_failure; |
| 204 | spin_unlock(&s->tcf_lock); | 207 | spin_unlock_bh(&s->tcf_lock); |
| 205 | 208 | ||
| 206 | return skb->len; | 209 | return skb->len; |
| 207 | 210 | ||
| 208 | nla_put_failure: | 211 | nla_put_failure: |
| 209 | spin_unlock(&s->tcf_lock); | 212 | spin_unlock_bh(&s->tcf_lock); |
| 210 | nlmsg_trim(skb, b); | 213 | nlmsg_trim(skb, b); |
| 211 | return -1; | 214 | return -1; |
| 212 | } | 215 | } |
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c index ba2ae9f75ef5..8f09cf08d8fe 100644 --- a/net/sched/act_tunnel_key.c +++ b/net/sched/act_tunnel_key.c | |||
| @@ -354,11 +354,11 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, | |||
| 354 | params_new->tcft_action = parm->t_action; | 354 | params_new->tcft_action = parm->t_action; |
| 355 | params_new->tcft_enc_metadata = metadata; | 355 | params_new->tcft_enc_metadata = metadata; |
| 356 | 356 | ||
| 357 | spin_lock(&t->tcf_lock); | 357 | spin_lock_bh(&t->tcf_lock); |
| 358 | t->tcf_action = parm->action; | 358 | t->tcf_action = parm->action; |
| 359 | rcu_swap_protected(t->params, params_new, | 359 | rcu_swap_protected(t->params, params_new, |
| 360 | lockdep_is_held(&t->tcf_lock)); | 360 | lockdep_is_held(&t->tcf_lock)); |
| 361 | spin_unlock(&t->tcf_lock); | 361 | spin_unlock_bh(&t->tcf_lock); |
| 362 | if (params_new) | 362 | if (params_new) |
| 363 | kfree_rcu(params_new, rcu); | 363 | kfree_rcu(params_new, rcu); |
| 364 | 364 | ||
| @@ -485,7 +485,7 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 485 | }; | 485 | }; |
| 486 | struct tcf_t tm; | 486 | struct tcf_t tm; |
| 487 | 487 | ||
| 488 | spin_lock(&t->tcf_lock); | 488 | spin_lock_bh(&t->tcf_lock); |
| 489 | params = rcu_dereference_protected(t->params, | 489 | params = rcu_dereference_protected(t->params, |
| 490 | lockdep_is_held(&t->tcf_lock)); | 490 | lockdep_is_held(&t->tcf_lock)); |
| 491 | opt.action = t->tcf_action; | 491 | opt.action = t->tcf_action; |
| @@ -520,12 +520,12 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 520 | if (nla_put_64bit(skb, TCA_TUNNEL_KEY_TM, sizeof(tm), | 520 | if (nla_put_64bit(skb, TCA_TUNNEL_KEY_TM, sizeof(tm), |
| 521 | &tm, TCA_TUNNEL_KEY_PAD)) | 521 | &tm, TCA_TUNNEL_KEY_PAD)) |
| 522 | goto nla_put_failure; | 522 | goto nla_put_failure; |
| 523 | spin_unlock(&t->tcf_lock); | 523 | spin_unlock_bh(&t->tcf_lock); |
| 524 | 524 | ||
| 525 | return skb->len; | 525 | return skb->len; |
| 526 | 526 | ||
| 527 | nla_put_failure: | 527 | nla_put_failure: |
| 528 | spin_unlock(&t->tcf_lock); | 528 | spin_unlock_bh(&t->tcf_lock); |
| 529 | nlmsg_trim(skb, b); | 529 | nlmsg_trim(skb, b); |
| 530 | return -1; | 530 | return -1; |
| 531 | } | 531 | } |
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index d1f5028384c9..209e70ad2c09 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c | |||
| @@ -213,10 +213,10 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 213 | p->tcfv_push_prio = push_prio; | 213 | p->tcfv_push_prio = push_prio; |
| 214 | p->tcfv_push_proto = push_proto; | 214 | p->tcfv_push_proto = push_proto; |
| 215 | 215 | ||
| 216 | spin_lock(&v->tcf_lock); | 216 | spin_lock_bh(&v->tcf_lock); |
| 217 | v->tcf_action = parm->action; | 217 | v->tcf_action = parm->action; |
| 218 | rcu_swap_protected(v->vlan_p, p, lockdep_is_held(&v->tcf_lock)); | 218 | rcu_swap_protected(v->vlan_p, p, lockdep_is_held(&v->tcf_lock)); |
| 219 | spin_unlock(&v->tcf_lock); | 219 | spin_unlock_bh(&v->tcf_lock); |
| 220 | 220 | ||
| 221 | if (p) | 221 | if (p) |
| 222 | kfree_rcu(p, rcu); | 222 | kfree_rcu(p, rcu); |
| @@ -249,7 +249,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 249 | }; | 249 | }; |
| 250 | struct tcf_t t; | 250 | struct tcf_t t; |
| 251 | 251 | ||
| 252 | spin_lock(&v->tcf_lock); | 252 | spin_lock_bh(&v->tcf_lock); |
| 253 | opt.action = v->tcf_action; | 253 | opt.action = v->tcf_action; |
| 254 | p = rcu_dereference_protected(v->vlan_p, lockdep_is_held(&v->tcf_lock)); | 254 | p = rcu_dereference_protected(v->vlan_p, lockdep_is_held(&v->tcf_lock)); |
| 255 | opt.v_action = p->tcfv_action; | 255 | opt.v_action = p->tcfv_action; |
| @@ -268,12 +268,12 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 268 | tcf_tm_dump(&t, &v->tcf_tm); | 268 | tcf_tm_dump(&t, &v->tcf_tm); |
| 269 | if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD)) | 269 | if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD)) |
| 270 | goto nla_put_failure; | 270 | goto nla_put_failure; |
| 271 | spin_unlock(&v->tcf_lock); | 271 | spin_unlock_bh(&v->tcf_lock); |
| 272 | 272 | ||
| 273 | return skb->len; | 273 | return skb->len; |
| 274 | 274 | ||
| 275 | nla_put_failure: | 275 | nla_put_failure: |
| 276 | spin_unlock(&v->tcf_lock); | 276 | spin_unlock_bh(&v->tcf_lock); |
| 277 | nlmsg_trim(skb, b); | 277 | nlmsg_trim(skb, b); |
| 278 | return -1; | 278 | return -1; |
| 279 | } | 279 | } |
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c index af16f36ed578..856fa79d4ffd 100644 --- a/net/sched/cls_matchall.c +++ b/net/sched/cls_matchall.c | |||
| @@ -113,6 +113,8 @@ static void mall_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) | |||
| 113 | if (!head) | 113 | if (!head) |
| 114 | return; | 114 | return; |
| 115 | 115 | ||
| 116 | tcf_unbind_filter(tp, &head->res); | ||
| 117 | |||
| 116 | if (!tc_skip_hw(head->flags)) | 118 | if (!tc_skip_hw(head->flags)) |
| 117 | mall_destroy_hw_filter(tp, head, (unsigned long) head, extack); | 119 | mall_destroy_hw_filter(tp, head, (unsigned long) head, extack); |
| 118 | 120 | ||
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index b09867c8b817..93c0c225ab34 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | MODULE_AUTHOR("Mellanox Technologies"); | 45 | MODULE_AUTHOR("Mellanox Technologies"); |
| 46 | MODULE_DESCRIPTION("Transport Layer Security Support"); | 46 | MODULE_DESCRIPTION("Transport Layer Security Support"); |
| 47 | MODULE_LICENSE("Dual BSD/GPL"); | 47 | MODULE_LICENSE("Dual BSD/GPL"); |
| 48 | MODULE_ALIAS_TCP_ULP("tls"); | ||
| 48 | 49 | ||
| 49 | enum { | 50 | enum { |
| 50 | TLSV4, | 51 | TLSV4, |
diff --git a/samples/bpf/xdp_redirect_cpu_user.c b/samples/bpf/xdp_redirect_cpu_user.c index 9a6c7e0a6dd1..2d23054aaccf 100644 --- a/samples/bpf/xdp_redirect_cpu_user.c +++ b/samples/bpf/xdp_redirect_cpu_user.c | |||
| @@ -679,8 +679,9 @@ int main(int argc, char **argv) | |||
| 679 | return EXIT_FAIL_OPTION; | 679 | return EXIT_FAIL_OPTION; |
| 680 | } | 680 | } |
| 681 | 681 | ||
| 682 | /* Remove XDP program when program is interrupted */ | 682 | /* Remove XDP program when program is interrupted or killed */ |
| 683 | signal(SIGINT, int_exit); | 683 | signal(SIGINT, int_exit); |
| 684 | signal(SIGTERM, int_exit); | ||
| 684 | 685 | ||
| 685 | if (bpf_set_link_xdp_fd(ifindex, prog_fd[prog_num], xdp_flags) < 0) { | 686 | if (bpf_set_link_xdp_fd(ifindex, prog_fd[prog_num], xdp_flags) < 0) { |
| 686 | fprintf(stderr, "link set xdp fd failed\n"); | 687 | fprintf(stderr, "link set xdp fd failed\n"); |
diff --git a/samples/bpf/xdp_rxq_info_user.c b/samples/bpf/xdp_rxq_info_user.c index 248a7eab9531..ef26f882f92f 100644 --- a/samples/bpf/xdp_rxq_info_user.c +++ b/samples/bpf/xdp_rxq_info_user.c | |||
| @@ -567,8 +567,9 @@ int main(int argc, char **argv) | |||
| 567 | exit(EXIT_FAIL_BPF); | 567 | exit(EXIT_FAIL_BPF); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | /* Remove XDP program when program is interrupted */ | 570 | /* Remove XDP program when program is interrupted or killed */ |
| 571 | signal(SIGINT, int_exit); | 571 | signal(SIGINT, int_exit); |
| 572 | signal(SIGTERM, int_exit); | ||
| 572 | 573 | ||
| 573 | if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) { | 574 | if (bpf_set_link_xdp_fd(ifindex, prog_fd, xdp_flags) < 0) { |
| 574 | fprintf(stderr, "link set xdp fd failed\n"); | 575 | fprintf(stderr, "link set xdp fd failed\n"); |
diff --git a/tools/testing/selftests/bpf/test_cgroup_storage.c b/tools/testing/selftests/bpf/test_cgroup_storage.c index dc83fb2d3f27..4e196e3bfecf 100644 --- a/tools/testing/selftests/bpf/test_cgroup_storage.c +++ b/tools/testing/selftests/bpf/test_cgroup_storage.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <stdio.h> | 5 | #include <stdio.h> |
| 6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
| 7 | 7 | ||
| 8 | #include "bpf_rlimit.h" | ||
| 8 | #include "cgroup_helpers.h" | 9 | #include "cgroup_helpers.h" |
| 9 | 10 | ||
| 10 | char bpf_log_buf[BPF_LOG_BUF_SIZE]; | 11 | char bpf_log_buf[BPF_LOG_BUF_SIZE]; |
