Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 11 Jun 2018 02:25:23 +0000 (19:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 11 Jun 2018 02:25:23 +0000 (19:25 -0700)
Pull networking fixes from David Miller:

 1) Fix several bpfilter/UMH bugs, in particular make the UMH build not
    depend upon X86 specific Kconfig symbols. From Alexei Starovoitov.

 2) Fix handling of modified context pointer in bpf verifier, from
    Daniel Borkmann.

 3) Kill regression in ifdown/ifup sequences for hv_netvsc driver, from
    Dexuan Cui.

 4) When the bonding primary member name changes, we have to re-evaluate
    the bond->force_primary setting, from Xiangning Yu.

 5) Eliminate possible padding beyone end of SKB in cdc_ncm driver, from
    Bjørn Mork.

 6) RX queue length reported for UDP sockets in procfs and socket diag
    are inaccurate, from Paolo Abeni.

 7) Fix br_fdb_find_port() locking, from Petr Machata.

 8) Limit sk_rcvlowat values properly in TCP, from Soheil Hassas
    Yeganeh.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (23 commits)
  tcp: limit sk_rcvlowat by the maximum receive buffer
  net: phy: dp83822: use BMCR_ANENABLE instead of BMSR_ANEGCAPABLE for DP83620
  socket: close race condition between sock_close() and sockfs_setattr()
  net: bridge: Fix locking in br_fdb_find_port()
  udp: fix rx queue len reported by diag and proc interface
  cdc_ncm: avoid padding beyond end of skb
  net/sched: act_simple: fix parsing of TCA_DEF_DATA
  net: fddi: fix a possible null-ptr-deref
  net: aquantia: fix unsigned numvecs comparison with less than zero
  net: stmmac: fix build failure due to missing COMMON_CLK dependency
  bpfilter: fix race in pipe access
  bpf, xdp: fix crash in xdp_umem_unaccount_pages
  xsk: Fix umem fill/completion queue mmap on 32-bit
  tools/bpf: fix selftest get_cgroup_id_user
  bpfilter: fix OUTPUT_FORMAT
  umh: fix race condition
  net: mscc: ocelot: Fix uninitialized error in ocelot_netdevice_event()
  bonding: re-evaluate force_primary when the primary slave name changes
  ip_tunnel: Fix name string concatenate in __ip_tunnel_create()
  hv_netvsc: Fix a network regression after ifdown/ifup
  ...

37 files changed:
arch/um/drivers/vector_transports.c
drivers/net/bonding/bond_options.c
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/stmicro/stmmac/Kconfig
drivers/net/fddi/skfp/skfddi.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/phy/dp83848.c
drivers/net/tap.c
drivers/net/tun.c
drivers/net/usb/cdc_ncm.c
drivers/net/virtio_net.c
include/linux/virtio_net.h
include/net/transp_v6.h
include/net/udp.h
include/uapi/linux/if_xdp.h
include/uapi/linux/netfilter/nf_tables.h
kernel/bpf/verifier.c
kernel/umh.c
net/bpfilter/Makefile
net/bpfilter/bpfilter_kern.c
net/bridge/br_fdb.c
net/ipv4/ip_tunnel.c
net/ipv4/tcp.c
net/ipv4/udp.c
net/ipv4/udp_diag.c
net/ipv6/datagram.c
net/ipv6/udp.c
net/netfilter/nft_log.c
net/packet/af_packet.c
net/sched/act_simple.c
net/socket.c
net/xdp/xdp_umem.c
net/xdp/xsk.c
tools/testing/selftests/bpf/get_cgroup_id_kern.c
tools/testing/selftests/bpf/get_cgroup_id_user.c
tools/testing/selftests/bpf/test_verifier.c

index 9065047f844baee5c19574f4c12e8f3bd6e280bc..77e4ebc206ae1da08ac341010300ed8a0526b000 100644 (file)
@@ -120,7 +120,8 @@ static int raw_form_header(uint8_t *header,
                skb,
                vheader,
                virtio_legacy_is_little_endian(),
-               false
+               false,
+               0
        );
 
        return 0;
index 8a945c9341d6adde8ffa49fcc2c11a06860a17c7..98663c50ded0b4b3f784be23baa8fa0e19b419ee 100644 (file)
@@ -1142,6 +1142,7 @@ static int bond_option_primary_set(struct bonding *bond,
                                   slave->dev->name);
                        rcu_assign_pointer(bond->primary_slave, slave);
                        strcpy(bond->params.primary, slave->dev->name);
+                       bond->force_primary = true;
                        bond_select_active_slave(bond);
                        goto out;
                }
index a50e08bb4748386f999b1898b8207d973ac3508b..750007513f9dc7cd48c852f586f82e3b172fafd2 100644 (file)
@@ -267,14 +267,13 @@ static int aq_pci_probe(struct pci_dev *pdev,
        numvecs = min(numvecs, num_online_cpus());
        /*enable interrupts */
 #if !AQ_CFG_FORCE_LEGACY_INT
-       numvecs = pci_alloc_irq_vectors(self->pdev, 1, numvecs,
-                                       PCI_IRQ_MSIX | PCI_IRQ_MSI |
-                                       PCI_IRQ_LEGACY);
+       err = pci_alloc_irq_vectors(self->pdev, 1, numvecs,
+                                   PCI_IRQ_MSIX | PCI_IRQ_MSI |
+                                   PCI_IRQ_LEGACY);
 
-       if (numvecs < 0) {
-               err = numvecs;
+       if (err < 0)
                goto err_hwinit;
-       }
+       numvecs = err;
 #endif
        self->irqvecs = numvecs;
 
index c8c74aa548d96e00bbad834b943bf2365df7bdad..fb2c8f8071e64d3b6d52865ecaddf17f841a2b9d 100644 (file)
@@ -1126,7 +1126,7 @@ static int ocelot_netdevice_event(struct notifier_block *unused,
 {
        struct netdev_notifier_changeupper_info *info = ptr;
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-       int ret;
+       int ret = 0;
 
        if (netif_is_lag_master(dev)) {
                struct net_device *slave;
index e28c0d2c58e911ed2e04175ccb4cca50f9fc0107..cb5b0f58c395c2bdbf32e7283d91cf8c4ac5dbe9 100644 (file)
@@ -33,7 +33,7 @@ config DWMAC_DWC_QOS_ETH
        select PHYLIB
        select CRC32
        select MII
-       depends on OF && HAS_DMA
+       depends on OF && COMMON_CLK && HAS_DMA
        help
          Support for chips using the snps,dwc-qos-ethernet.txt DT binding.
 
@@ -57,7 +57,7 @@ config DWMAC_ANARION
 config DWMAC_IPQ806X
        tristate "QCA IPQ806x DWMAC support"
        default ARCH_QCOM
-       depends on OF && (ARCH_QCOM || COMPILE_TEST)
+       depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
        select MFD_SYSCON
        help
          Support for QCA IPQ806X DWMAC Ethernet.
@@ -100,7 +100,7 @@ config DWMAC_OXNAS
 config DWMAC_ROCKCHIP
        tristate "Rockchip dwmac support"
        default ARCH_ROCKCHIP
-       depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
+       depends on OF && COMMON_CLK && (ARCH_ROCKCHIP || COMPILE_TEST)
        select MFD_SYSCON
        help
          Support for Ethernet controller on Rockchip RK3288 SoC.
@@ -123,7 +123,7 @@ config DWMAC_SOCFPGA
 config DWMAC_STI
        tristate "STi GMAC support"
        default ARCH_STI
-       depends on OF && (ARCH_STI || COMPILE_TEST)
+       depends on OF && COMMON_CLK && (ARCH_STI || COMPILE_TEST)
        select MFD_SYSCON
        ---help---
          Support for ethernet controller on STi SOCs.
@@ -147,7 +147,7 @@ config DWMAC_STM32
 config DWMAC_SUNXI
        tristate "Allwinner GMAC support"
        default ARCH_SUNXI
-       depends on OF && (ARCH_SUNXI || COMPILE_TEST)
+       depends on OF && COMMON_CLK && (ARCH_SUNXI || COMPILE_TEST)
        ---help---
          Support for Allwinner A20/A31 GMAC ethernet controllers.
 
index 2414f1dc8ddd8e10a36f8f279bca0a64bb24acf8..72433f3efc747e78b83ae32ac91a203d7aed3914 100644 (file)
@@ -297,11 +297,11 @@ static int skfp_init_one(struct pci_dev *pdev,
        return 0;
 err_out5:
        if (smc->os.SharedMemAddr) 
-               pci_free_consistent(pdev, smc->os.SharedMemSize,
-                                   smc->os.SharedMemAddr, 
-                                   smc->os.SharedMemDMA);
-       pci_free_consistent(pdev, MAX_FRAME_SIZE,
-                           smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
+               dma_free_coherent(&pdev->dev, smc->os.SharedMemSize,
+                                 smc->os.SharedMemAddr,
+                                 smc->os.SharedMemDMA);
+       dma_free_coherent(&pdev->dev, MAX_FRAME_SIZE,
+                         smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
 err_out4:
        free_netdev(dev);
 err_out3:
@@ -328,17 +328,17 @@ static void skfp_remove_one(struct pci_dev *pdev)
        unregister_netdev(p);
 
        if (lp->os.SharedMemAddr) {
-               pci_free_consistent(&lp->os.pdev,
-                                   lp->os.SharedMemSize,
-                                   lp->os.SharedMemAddr,
-                                   lp->os.SharedMemDMA);
+               dma_free_coherent(&pdev->dev,
+                                 lp->os.SharedMemSize,
+                                 lp->os.SharedMemAddr,
+                                 lp->os.SharedMemDMA);
                lp->os.SharedMemAddr = NULL;
        }
        if (lp->os.LocalRxBuffer) {
-               pci_free_consistent(&lp->os.pdev,
-                                   MAX_FRAME_SIZE,
-                                   lp->os.LocalRxBuffer,
-                                   lp->os.LocalRxBufferDMA);
+               dma_free_coherent(&pdev->dev,
+                                 MAX_FRAME_SIZE,
+                                 lp->os.LocalRxBuffer,
+                                 lp->os.LocalRxBufferDMA);
                lp->os.LocalRxBuffer = NULL;
        }
 #ifdef MEM_MAPPED_IO
@@ -394,7 +394,9 @@ static  int skfp_driver_init(struct net_device *dev)
        spin_lock_init(&bp->DriverLock);
        
        // Allocate invalid frame
-       bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA);
+       bp->LocalRxBuffer = dma_alloc_coherent(&bp->pdev.dev, MAX_FRAME_SIZE,
+                                              &bp->LocalRxBufferDMA,
+                                              GFP_ATOMIC);
        if (!bp->LocalRxBuffer) {
                printk("could not allocate mem for ");
                printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE);
@@ -407,23 +409,22 @@ static  int skfp_driver_init(struct net_device *dev)
        if (bp->SharedMemSize > 0) {
                bp->SharedMemSize += 16;        // for descriptor alignment
 
-               bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
-                                                        bp->SharedMemSize,
-                                                        &bp->SharedMemDMA);
+               bp->SharedMemAddr = dma_zalloc_coherent(&bp->pdev.dev,
+                                                       bp->SharedMemSize,
+                                                       &bp->SharedMemDMA,
+                                                       GFP_ATOMIC);
                if (!bp->SharedMemAddr) {
                        printk("could not allocate mem for ");
                        printk("hardware module: %ld byte\n",
                               bp->SharedMemSize);
                        goto fail;
                }
-               bp->SharedMemHeap = 0;  // Nothing used yet.
 
        } else {
                bp->SharedMemAddr = NULL;
-               bp->SharedMemHeap = 0;
-       }                       // SharedMemSize > 0
+       }
 
-       memset(bp->SharedMemAddr, 0, bp->SharedMemSize);
+       bp->SharedMemHeap = 0;
 
        card_stop(smc);         // Reset adapter.
 
@@ -442,15 +443,15 @@ static  int skfp_driver_init(struct net_device *dev)
 
 fail:
        if (bp->SharedMemAddr) {
-               pci_free_consistent(&bp->pdev,
-                                   bp->SharedMemSize,
-                                   bp->SharedMemAddr,
-                                   bp->SharedMemDMA);
+               dma_free_coherent(&bp->pdev.dev,
+                                 bp->SharedMemSize,
+                                 bp->SharedMemAddr,
+                                 bp->SharedMemDMA);
                bp->SharedMemAddr = NULL;
        }
        if (bp->LocalRxBuffer) {
-               pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE,
-                                   bp->LocalRxBuffer, bp->LocalRxBufferDMA);
+               dma_free_coherent(&bp->pdev.dev, MAX_FRAME_SIZE,
+                                 bp->LocalRxBuffer, bp->LocalRxBufferDMA);
                bp->LocalRxBuffer = NULL;
        }
        return err;
index 1e9bde68698d6b661ad4443c63db4f49d4ac7e82..7b18a8c267c2b88d2c5e84bfa87da9691883c154 100644 (file)
@@ -125,8 +125,10 @@ static int netvsc_open(struct net_device *net)
        }
 
        rdev = nvdev->extension;
-       if (!rdev->link_state)
+       if (!rdev->link_state) {
                netif_carrier_on(net);
+               netif_tx_wake_all_queues(net);
+       }
 
        if (vf_netdev) {
                /* Setting synthetic device up transparently sets
index cd09c3af21179fb14af0925f252d308897519cab..6e8e42361fd5406e7d345bd9aefbc00e950f2cc5 100644 (file)
@@ -74,6 +74,25 @@ static int dp83848_config_intr(struct phy_device *phydev)
        return phy_write(phydev, DP83848_MICR, control);
 }
 
+static int dp83848_config_init(struct phy_device *phydev)
+{
+       int err;
+       int val;
+
+       err = genphy_config_init(phydev);
+       if (err < 0)
+               return err;
+
+       /* DP83620 always reports Auto Negotiation Ability on BMSR. Instead,
+        * we check initial value of BMCR Auto negotiation enable bit
+        */
+       val = phy_read(phydev, MII_BMCR);
+       if (!(val & BMCR_ANENABLE))
+               phydev->autoneg = AUTONEG_DISABLE;
+
+       return 0;
+}
+
 static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
        { TI_DP83848C_PHY_ID, 0xfffffff0 },
        { NS_DP83848C_PHY_ID, 0xfffffff0 },
@@ -83,7 +102,7 @@ static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
 };
 MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
 
-#define DP83848_PHY_DRIVER(_id, _name)                         \
+#define DP83848_PHY_DRIVER(_id, _name, _config_init)           \
        {                                                       \
                .phy_id         = _id,                          \
                .phy_id_mask    = 0xfffffff0,                   \
@@ -92,7 +111,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
                .flags          = PHY_HAS_INTERRUPT,            \
                                                                \
                .soft_reset     = genphy_soft_reset,            \
-               .config_init    = genphy_config_init,           \
+               .config_init    = _config_init,                 \
                .suspend        = genphy_suspend,               \
                .resume         = genphy_resume,                \
                                                                \
@@ -102,10 +121,14 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
        }
 
 static struct phy_driver dp83848_driver[] = {
-       DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"),
-       DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY"),
-       DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY"),
-       DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"),
+       DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY",
+                          genphy_config_init),
+       DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY",
+                          genphy_config_init),
+       DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY",
+                          dp83848_config_init),
+       DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY",
+                          genphy_config_init),
 };
 module_phy_driver(dp83848_driver);
 
index 9b6cb780affec603f8200d258988785c5edf55a0..f0f7cd9776671fb6d3f3dd6498611afe593b41c3 100644 (file)
@@ -774,13 +774,16 @@ static ssize_t tap_put_user(struct tap_queue *q,
        int total;
 
        if (q->flags & IFF_VNET_HDR) {
+               int vlan_hlen = skb_vlan_tag_present(skb) ? VLAN_HLEN : 0;
                struct virtio_net_hdr vnet_hdr;
+
                vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
                if (iov_iter_count(iter) < vnet_hdr_len)
                        return -EINVAL;
 
                if (virtio_net_hdr_from_skb(skb, &vnet_hdr,
-                                           tap_is_little_endian(q), true))
+                                           tap_is_little_endian(q), true,
+                                           vlan_hlen))
                        BUG();
 
                if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) !=
index 85e14adf520747c3f284472b89e30048e4b35451..a192a017cc68878360505b93df151de3d0b9b730 100644 (file)
@@ -2089,7 +2089,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
                        return -EINVAL;
 
                if (virtio_net_hdr_from_skb(skb, &gso,
-                                           tun_is_little_endian(tun), true)) {
+                                           tun_is_little_endian(tun), true,
+                                           vlan_hlen)) {
                        struct skb_shared_info *sinfo = skb_shinfo(skb);
                        pr_err("unexpected GSO type: "
                               "0x%x, gso_size %d, hdr_len %d\n",
index 90d07ed224d5bb911cc130da51336e48bf98824e..b0e8b9613054137215e2f502f9deeab3bbad8f80 100644 (file)
@@ -1124,7 +1124,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
         * accordingly. Otherwise, we should check here.
         */
        if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
-               delayed_ndp_size = ctx->max_ndp_size;
+               delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus);
        else
                delayed_ndp_size = 0;
 
@@ -1285,7 +1285,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
        /* If requested, put NDP at end of frame. */
        if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
                nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
-               cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size);
+               cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size);
                nth16->wNdpIndex = cpu_to_le16(skb_out->len);
                skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size);
 
index 2aaa18ec7d460fde599aa0508b485077a47ee3e5..1619ee3070b6213cb9b9cc65e8fb146a2894ebdf 100644 (file)
@@ -1411,7 +1411,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
                hdr = skb_vnet_hdr(skb);
 
        if (virtio_net_hdr_from_skb(skb, &hdr->hdr,
-                                   virtio_is_little_endian(vi->vdev), false))
+                                   virtio_is_little_endian(vi->vdev), false,
+                                   0))
                BUG();
 
        if (vi->mergeable_rx_bufs)
index f144216febc642fd70512df9dddefe1a7f119478..9397628a196714dc2177552465fe91fd18b9627d 100644 (file)
@@ -58,7 +58,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
                                          struct virtio_net_hdr *hdr,
                                          bool little_endian,
-                                         bool has_data_valid)
+                                         bool has_data_valid,
+                                         int vlan_hlen)
 {
        memset(hdr, 0, sizeof(*hdr));   /* no info leak */
 
@@ -83,12 +84,8 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
 
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
-               if (skb_vlan_tag_present(skb))
-                       hdr->csum_start = __cpu_to_virtio16(little_endian,
-                               skb_checksum_start_offset(skb) + VLAN_HLEN);
-               else
-                       hdr->csum_start = __cpu_to_virtio16(little_endian,
-                               skb_checksum_start_offset(skb));
+               hdr->csum_start = __cpu_to_virtio16(little_endian,
+                       skb_checksum_start_offset(skb) + vlan_hlen);
                hdr->csum_offset = __cpu_to_virtio16(little_endian,
                                skb->csum_offset);
        } else if (has_data_valid &&
index c4f5caaf37786d54596ab63aac497b7e06066af8..f6a3543e52477d0b3ec6c883fff554c4e924e0d6 100644 (file)
@@ -45,8 +45,15 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg,
                          struct flowi6 *fl6, struct ipcm6_cookie *ipc6,
                          struct sockcm_cookie *sockc);
 
-void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
-                            __u16 srcp, __u16 destp, int bucket);
+void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
+                              __u16 srcp, __u16 destp, int rqueue, int bucket);
+static inline void
+ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, __u16 srcp,
+                       __u16 destp, int bucket)
+{
+       __ip6_dgram_sock_seq_show(seq, sp, srcp, destp, sk_rmem_alloc_get(sp),
+                                 bucket);
+}
 
 #define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006)
 
index 7ba0ed252c52c0ad248abac3e4a0a157c575e4ad..b1ea8b0f5e6a8ce82602e593acd583170b4a6e73 100644 (file)
@@ -247,6 +247,11 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb,
        return htons((((u64) hash * (max - min)) >> 32) + min);
 }
 
+static inline int udp_rqueue_get(struct sock *sk)
+{
+       return sk_rmem_alloc_get(sk) - READ_ONCE(udp_sk(sk)->forward_deficit);
+}
+
 /* net/ipv4/udp.c */
 void udp_destruct_sock(struct sock *sk);
 void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len);
index 1fa0e977ea8d0224d3770afd8a9026f361f6ae0c..caed8b1614ffc0aae5e43ffca0c403a0c7b9401f 100644 (file)
@@ -63,8 +63,8 @@ struct xdp_statistics {
 /* Pgoff for mmaping the rings */
 #define XDP_PGOFF_RX_RING                        0
 #define XDP_PGOFF_TX_RING               0x80000000
-#define XDP_UMEM_PGOFF_FILL_RING       0x100000000
-#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000
+#define XDP_UMEM_PGOFF_FILL_RING       0x100000000ULL
+#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000ULL
 
 /* Rx/Tx descriptor */
 struct xdp_desc {
index ae00a3c49b8a461a69f7f0a6374252d05d9369c8..c9bf74b94f3704ca66791df3564f01569ec4ba30 100644 (file)
@@ -1099,9 +1099,31 @@ enum nft_log_attributes {
 #define NFTA_LOG_MAX           (__NFTA_LOG_MAX - 1)
 
 /**
- * LOGLEVEL_AUDIT - a pseudo log level enabling audit logging
- */
-#define LOGLEVEL_AUDIT         8
+ * enum nft_log_level - nf_tables log levels
+ *
+ * @NFT_LOGLEVEL_EMERG: system is unusable
+ * @NFT_LOGLEVEL_ALERT: action must be taken immediately
+ * @NFT_LOGLEVEL_CRIT: critical conditions
+ * @NFT_LOGLEVEL_ERR: error conditions
+ * @NFT_LOGLEVEL_WARNING: warning conditions
+ * @NFT_LOGLEVEL_NOTICE: normal but significant condition
+ * @NFT_LOGLEVEL_INFO: informational
+ * @NFT_LOGLEVEL_DEBUG: debug-level messages
+ * @NFT_LOGLEVEL_AUDIT: enabling audit logging
+ */
+enum nft_log_level {
+       NFT_LOGLEVEL_EMERG,
+       NFT_LOGLEVEL_ALERT,
+       NFT_LOGLEVEL_CRIT,
+       NFT_LOGLEVEL_ERR,
+       NFT_LOGLEVEL_WARNING,
+       NFT_LOGLEVEL_NOTICE,
+       NFT_LOGLEVEL_INFO,
+       NFT_LOGLEVEL_DEBUG,
+       NFT_LOGLEVEL_AUDIT,
+       __NFT_LOGLEVEL_MAX
+};
+#define NFT_LOGLEVEL_MAX       (__NFT_LOGLEVEL_MAX + 1)
 
 /**
  * enum nft_queue_attributes - nf_tables queue expression netlink attributes
index d6403b5166f4934e733f53367b82c0d468ba32cb..cced0c1e63e2d62f2bd60795e29b6cfbc8c0df93 100644 (file)
@@ -1617,6 +1617,30 @@ static int get_callee_stack_depth(struct bpf_verifier_env *env,
 }
 #endif
 
+static int check_ctx_reg(struct bpf_verifier_env *env,
+                        const struct bpf_reg_state *reg, int regno)
+{
+       /* Access to ctx or passing it to a helper is only allowed in
+        * its original, unmodified form.
+        */
+
+       if (reg->off) {
+               verbose(env, "dereference of modified ctx ptr R%d off=%d disallowed\n",
+                       regno, reg->off);
+               return -EACCES;
+       }
+
+       if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
+               char tn_buf[48];
+
+               tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
+               verbose(env, "variable ctx access var_off=%s disallowed\n", tn_buf);
+               return -EACCES;
+       }
+
+       return 0;
+}
+
 /* truncate register to smaller size (in bytes)
  * must be called with size < BPF_REG_SIZE
  */
@@ -1686,24 +1710,11 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
                        verbose(env, "R%d leaks addr into ctx\n", value_regno);
                        return -EACCES;
                }
-               /* ctx accesses must be at a fixed offset, so that we can
-                * determine what type of data were returned.
-                */
-               if (reg->off) {
-                       verbose(env,
-                               "dereference of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n",
-                               regno, reg->off, off - reg->off);
-                       return -EACCES;
-               }
-               if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
-                       char tn_buf[48];
 
-                       tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
-                       verbose(env,
-                               "variable ctx access var_off=%s off=%d size=%d",
-                               tn_buf, off, size);
-                       return -EACCES;
-               }
+               err = check_ctx_reg(env, reg, regno);
+               if (err < 0)
+                       return err;
+
                err = check_ctx_access(env, insn_idx, off, size, t, &reg_type);
                if (!err && t == BPF_READ && value_regno >= 0) {
                        /* ctx access returns either a scalar, or a
@@ -1984,6 +1995,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
                expected_type = PTR_TO_CTX;
                if (type != expected_type)
                        goto err_type;
+               err = check_ctx_reg(env, reg, regno);
+               if (err < 0)
+                       return err;
        } else if (arg_type_is_mem_ptr(arg_type)) {
                expected_type = PTR_TO_STACK;
                /* One exception here. In case function allows for NULL to be
index 30db93fd7e39b60eae6fb98aa31d8dc8106f1e56..c449858946afc23706e06ab1e893ba0cef4c4f99 100644 (file)
@@ -99,6 +99,7 @@ static int call_usermodehelper_exec_async(void *data)
 
        commit_creds(new);
 
+       sub_info->pid = task_pid_nr(current);
        if (sub_info->file)
                retval = do_execve_file(sub_info->file,
                                        sub_info->argv, sub_info->envp);
@@ -191,8 +192,6 @@ static void call_usermodehelper_exec_work(struct work_struct *work)
                if (pid < 0) {
                        sub_info->retval = pid;
                        umh_complete(sub_info);
-               } else {
-                       sub_info->pid = pid;
                }
        }
 }
index aafa72001fcd7c69b1a21d09e18fff7ac1b3c783..e0bbe7583e58dcca5e17136d1b091ff03465b4d2 100644 (file)
@@ -21,7 +21,7 @@ endif
 # which bpfilter_kern.c passes further into umh blob loader at run-time
 quiet_cmd_copy_umh = GEN $@
       cmd_copy_umh = echo ':' > $(obj)/.bpfilter_umh.o.cmd; \
-      $(OBJCOPY) -I binary -O $(CONFIG_OUTPUT_FORMAT) \
+      $(OBJCOPY) -I binary -O `$(OBJDUMP) -f $<|grep format|cut -d' ' -f8` \
       -B `$(OBJDUMP) -f $<|grep architecture|cut -d, -f1|cut -d' ' -f2` \
       --rename-section .data=.init.rodata $< $@
 
index b13d058f8c340915c077f25a0fe6fb77437a0bd3..09522573f611b01ba5fb4d52125e8264d9147f20 100644 (file)
@@ -24,17 +24,19 @@ static void shutdown_umh(struct umh_info *info)
 {
        struct task_struct *tsk;
 
+       if (!info->pid)
+               return;
        tsk = pid_task(find_vpid(info->pid), PIDTYPE_PID);
        if (tsk)
                force_sig(SIGKILL, tsk);
        fput(info->pipe_to_umh);
        fput(info->pipe_from_umh);
+       info->pid = 0;
 }
 
 static void __stop_umh(void)
 {
-       if (IS_ENABLED(CONFIG_INET) &&
-           bpfilter_process_sockopt) {
+       if (IS_ENABLED(CONFIG_INET)) {
                bpfilter_process_sockopt = NULL;
                shutdown_umh(&info);
        }
@@ -55,7 +57,7 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        struct mbox_reply reply;
        loff_t pos;
        ssize_t n;
-       int ret;
+       int ret = -EFAULT;
 
        req.is_set = is_set;
        req.pid = current->pid;
@@ -63,6 +65,8 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        req.addr = (long)optval;
        req.len = optlen;
        mutex_lock(&bpfilter_lock);
+       if (!info.pid)
+               goto out;
        n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos);
        if (n != sizeof(req)) {
                pr_err("write fail %zd\n", n);
index b19e3104afd6bf512d9b98f8350cc0f37d9880ea..502f663495308cde5b7d2a8bf841f6e0e7045130 100644 (file)
@@ -135,9 +135,11 @@ struct net_device *br_fdb_find_port(const struct net_device *br_dev,
                return NULL;
 
        br = netdev_priv(br_dev);
-       f = br_fdb_find(br, addr, vid);
+       rcu_read_lock();
+       f = br_fdb_find_rcu(br, addr, vid);
        if (f && f->dst)
                dev = f->dst->dev;
+       rcu_read_unlock();
 
        return dev;
 }
index 38d906baf1df837c5009b7487fb14f6a1c11acaa..c4f5602308edca064297fe8764764f65ebe84569 100644 (file)
@@ -261,8 +261,8 @@ static struct net_device *__ip_tunnel_create(struct net *net,
        } else {
                if (strlen(ops->kind) > (IFNAMSIZ - 3))
                        goto failed;
-               strlcpy(name, ops->kind, IFNAMSIZ);
-               strncat(name, "%d", 2);
+               strcpy(name, ops->kind);
+               strcat(name, "%d");
        }
 
        ASSERT_RTNL();
index 2741953adaba21d1fec1bdae8ff075255866fced..141acd92e58aeddeb9a0ba1eaacf3bd520a836a3 100644 (file)
@@ -1694,6 +1694,13 @@ EXPORT_SYMBOL(tcp_peek_len);
 /* Make sure sk_rcvbuf is big enough to satisfy SO_RCVLOWAT hint */
 int tcp_set_rcvlowat(struct sock *sk, int val)
 {
+       int cap;
+
+       if (sk->sk_userlocks & SOCK_RCVBUF_LOCK)
+               cap = sk->sk_rcvbuf >> 1;
+       else
+               cap = sock_net(sk)->ipv4.sysctl_tcp_rmem[2] >> 1;
+       val = min(val, cap);
        sk->sk_rcvlowat = val ? : 1;
 
        /* Check if we need to signal EPOLLIN right now */
@@ -1702,12 +1709,7 @@ int tcp_set_rcvlowat(struct sock *sk, int val)
        if (sk->sk_userlocks & SOCK_RCVBUF_LOCK)
                return 0;
 
-       /* val comes from user space and might be close to INT_MAX */
        val <<= 1;
-       if (val < 0)
-               val = INT_MAX;
-
-       val = min(val, sock_net(sk)->ipv4.sysctl_tcp_rmem[2]);
        if (val > sk->sk_rcvbuf) {
                sk->sk_rcvbuf = val;
                tcp_sk(sk)->window_clamp = tcp_win_from_space(sk, val);
index 3365362cac8814342ea8c760be8e79cfdcbe3f53..9bb27df4dac5ec5f133b15e972f384bdc1d165b1 100644 (file)
@@ -2772,7 +2772,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
                " %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d",
                bucket, src, srcp, dest, destp, sp->sk_state,
                sk_wmem_alloc_get(sp),
-               sk_rmem_alloc_get(sp),
+               udp_rqueue_get(sp),
                0, 0L, 0,
                from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
                0, sock_i_ino(sp),
index d0390d844ac840e4db3da1f9257e14ded78ba333..d9ad986c7b2c9e073616c63d6d5ab376d2b72d5f 100644 (file)
@@ -163,7 +163,7 @@ static int udp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh,
 static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
                void *info)
 {
-       r->idiag_rqueue = sk_rmem_alloc_get(sk);
+       r->idiag_rqueue = udp_rqueue_get(sk);
        r->idiag_wqueue = sk_wmem_alloc_get(sk);
 }
 
index a02ad100f0d75b487bf029ea0788033900373557..2ee08b6a86a4881210f5a0c81206a64a562e5a56 100644 (file)
@@ -1019,8 +1019,8 @@ exit_f:
 }
 EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl);
 
-void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
-                            __u16 srcp, __u16 destp, int bucket)
+void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
+                              __u16 srcp, __u16 destp, int rqueue, int bucket)
 {
        const struct in6_addr *dest, *src;
 
@@ -1036,7 +1036,7 @@ void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
                   dest->s6_addr32[2], dest->s6_addr32[3], destp,
                   sp->sk_state,
                   sk_wmem_alloc_get(sp),
-                  sk_rmem_alloc_get(sp),
+                  rqueue,
                   0, 0L, 0,
                   from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
                   0,
index 164afd31aebf13687ae2ca8963b1ea2c749dae5b..e6645cae403ed81004404049a1b95927921bfff6 100644 (file)
@@ -1523,7 +1523,8 @@ int udp6_seq_show(struct seq_file *seq, void *v)
                struct inet_sock *inet = inet_sk(v);
                __u16 srcp = ntohs(inet->inet_sport);
                __u16 destp = ntohs(inet->inet_dport);
-               ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket);
+               __ip6_dgram_sock_seq_show(seq, v, srcp, destp,
+                                         udp_rqueue_get(v), bucket);
        }
        return 0;
 }
index 7eef1cffbf1bc83bce99162ce00b2f03bc14f2cb..655187bed5d834cc71307cafcb3cdf5eb7424fa5 100644 (file)
@@ -111,7 +111,7 @@ static void nft_log_eval(const struct nft_expr *expr,
        const struct nft_log *priv = nft_expr_priv(expr);
 
        if (priv->loginfo.type == NF_LOG_TYPE_LOG &&
-           priv->loginfo.u.log.level == LOGLEVEL_AUDIT) {
+           priv->loginfo.u.log.level == NFT_LOGLEVEL_AUDIT) {
                nft_log_eval_audit(pkt);
                return;
        }
@@ -166,9 +166,9 @@ static int nft_log_init(const struct nft_ctx *ctx,
                        li->u.log.level =
                                ntohl(nla_get_be32(tb[NFTA_LOG_LEVEL]));
                } else {
-                       li->u.log.level = LOGLEVEL_WARNING;
+                       li->u.log.level = NFT_LOGLEVEL_WARNING;
                }
-               if (li->u.log.level > LOGLEVEL_AUDIT) {
+               if (li->u.log.level > NFT_LOGLEVEL_AUDIT) {
                        err = -EINVAL;
                        goto err1;
                }
@@ -196,7 +196,7 @@ static int nft_log_init(const struct nft_ctx *ctx,
                break;
        }
 
-       if (li->u.log.level == LOGLEVEL_AUDIT)
+       if (li->u.log.level == NFT_LOGLEVEL_AUDIT)
                return 0;
 
        err = nf_logger_find_get(ctx->family, li->type);
@@ -220,7 +220,7 @@ static void nft_log_destroy(const struct nft_ctx *ctx,
        if (priv->prefix != nft_log_null_prefix)
                kfree(priv->prefix);
 
-       if (li->u.log.level == LOGLEVEL_AUDIT)
+       if (li->u.log.level == NFT_LOGLEVEL_AUDIT)
                return;
 
        nf_logger_put(ctx->family, li->type);
index 54ce66f68482852a9896afbcbb2cf30cd4c7edfd..ee018564b2b4749d55c2080ac7ccd34fcd805e9a 100644 (file)
@@ -2005,7 +2005,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,
                return -EINVAL;
        *len -= sizeof(vnet_hdr);
 
-       if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true))
+       if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true, 0))
                return -EINVAL;
 
        return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr));
@@ -2272,7 +2272,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        if (do_vnet) {
                if (virtio_net_hdr_from_skb(skb, h.raw + macoff -
                                            sizeof(struct virtio_net_hdr),
-                                           vio_le(), true)) {
+                                           vio_le(), true, 0)) {
                        spin_lock(&sk->sk_receive_queue.lock);
                        goto drop_n_account;
                }
index 9618b4a83ceed37494025c57133975f2aaed5dd9..98c4afe7c15b29a99a3d18e06934e34f0732110d 100644 (file)
@@ -53,22 +53,22 @@ static void tcf_simp_release(struct tc_action *a)
        kfree(d->tcfd_defdata);
 }
 
-static int alloc_defdata(struct tcf_defact *d, char *defdata)
+static int alloc_defdata(struct tcf_defact *d, const struct nlattr *defdata)
 {
        d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL);
        if (unlikely(!d->tcfd_defdata))
                return -ENOMEM;
-       strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
+       nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
        return 0;
 }
 
-static void reset_policy(struct tcf_defact *d, char *defdata,
+static void reset_policy(struct tcf_defact *d, const struct nlattr *defdata,
                         struct tc_defact *p)
 {
        spin_lock_bh(&d->tcf_lock);
        d->tcf_action = p->action;
        memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
-       strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
+       nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
        spin_unlock_bh(&d->tcf_lock);
 }
 
@@ -87,7 +87,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        struct tcf_defact *d;
        bool exists = false;
        int ret = 0, err;
-       char *defdata;
 
        if (nla == NULL)
                return -EINVAL;
@@ -110,8 +109,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                return -EINVAL;
        }
 
-       defdata = nla_data(tb[TCA_DEF_DATA]);
-
        if (!exists) {
                ret = tcf_idr_create(tn, parm->index, est, a,
                                     &act_simp_ops, bind, false);
@@ -119,7 +116,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                        return ret;
 
                d = to_defact(*a);
-               ret = alloc_defdata(d, defdata);
+               ret = alloc_defdata(d, tb[TCA_DEF_DATA]);
                if (ret < 0) {
                        tcf_idr_release(*a, bind);
                        return ret;
@@ -133,7 +130,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
                if (!ovr)
                        return -EEXIST;
 
-               reset_policy(d, defdata, parm);
+               reset_policy(d, tb[TCA_DEF_DATA], parm);
        }
 
        if (ret == ACT_P_CREATED)
index af57d85bcb48bc61f44d88e9b49edb22d048c6c8..8a109012608a6132a65293c86cd175426b851cbe 100644 (file)
@@ -541,7 +541,10 @@ static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
        if (!err && (iattr->ia_valid & ATTR_UID)) {
                struct socket *sock = SOCKET_I(d_inode(dentry));
 
-               sock->sk->sk_uid = iattr->ia_uid;
+               if (sock->sk)
+                       sock->sk->sk_uid = iattr->ia_uid;
+               else
+                       err = -ENOENT;
        }
 
        return err;
@@ -590,12 +593,16 @@ EXPORT_SYMBOL(sock_alloc);
  *     an inode not a file.
  */
 
-void sock_release(struct socket *sock)
+static void __sock_release(struct socket *sock, struct inode *inode)
 {
        if (sock->ops) {
                struct module *owner = sock->ops->owner;
 
+               if (inode)
+                       inode_lock(inode);
                sock->ops->release(sock);
+               if (inode)
+                       inode_unlock(inode);
                sock->ops = NULL;
                module_put(owner);
        }
@@ -609,6 +616,11 @@ void sock_release(struct socket *sock)
        }
        sock->file = NULL;
 }
+
+void sock_release(struct socket *sock)
+{
+       __sock_release(sock, NULL);
+}
 EXPORT_SYMBOL(sock_release);
 
 void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
@@ -1171,7 +1183,7 @@ static int sock_mmap(struct file *file, struct vm_area_struct *vma)
 
 static int sock_close(struct inode *inode, struct file *filp)
 {
-       sock_release(SOCKET_I(inode));
+       __sock_release(SOCKET_I(inode), inode);
        return 0;
 }
 
index 7eb4948a38d23f80f80fad2b8d8f5e155c093c63..b9ef487c4618b56160ac73ed89271a6f03ebf371 100644 (file)
@@ -132,8 +132,10 @@ static void xdp_umem_unpin_pages(struct xdp_umem *umem)
 
 static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
 {
-       atomic_long_sub(umem->npgs, &umem->user->locked_vm);
-       free_uid(umem->user);
+       if (umem->user) {
+               atomic_long_sub(umem->npgs, &umem->user->locked_vm);
+               free_uid(umem->user);
+       }
 }
 
 static void xdp_umem_release(struct xdp_umem *umem)
index c6ed2454f7ce55e86bd8a8ea03773df6cb6f1414..36919a254ba370c37b4e199bfd68c285e25fdeb6 100644 (file)
@@ -643,7 +643,7 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname,
 static int xsk_mmap(struct file *file, struct socket *sock,
                    struct vm_area_struct *vma)
 {
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       loff_t offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
        unsigned long size = vma->vm_end - vma->vm_start;
        struct xdp_sock *xs = xdp_sk(sock->sk);
        struct xsk_queue *q = NULL;
index 2cf8cb23f209505b7f13e650861fc4cdc71988b1..014dba10b8a5dc1b6bb78ef54439c84c127bc13b 100644 (file)
@@ -11,12 +11,24 @@ struct bpf_map_def SEC("maps") cg_ids = {
        .max_entries = 1,
 };
 
+struct bpf_map_def SEC("maps") pidmap = {
+       .type = BPF_MAP_TYPE_ARRAY,
+       .key_size = sizeof(__u32),
+       .value_size = sizeof(__u32),
+       .max_entries = 1,
+};
+
 SEC("tracepoint/syscalls/sys_enter_nanosleep")
 int trace(void *ctx)
 {
-       __u32 key = 0;
+       __u32 pid = bpf_get_current_pid_tgid();
+       __u32 key = 0, *expected_pid;
        __u64 *val;
 
+       expected_pid = bpf_map_lookup_elem(&pidmap, &key);
+       if (!expected_pid || *expected_pid != pid)
+               return 0;
+
        val = bpf_map_lookup_elem(&cg_ids, &key);
        if (val)
                *val = bpf_get_current_cgroup_id();
index ea19a42e589405a0a6b3b1ee73207a48765047a1..e8da7b39158d415a125b28891cb345f8db34a212 100644 (file)
@@ -50,13 +50,13 @@ int main(int argc, char **argv)
        const char *probe_name = "syscalls/sys_enter_nanosleep";
        const char *file = "get_cgroup_id_kern.o";
        int err, bytes, efd, prog_fd, pmu_fd;
+       int cgroup_fd, cgidmap_fd, pidmap_fd;
        struct perf_event_attr attr = {};
-       int cgroup_fd, cgidmap_fd;
        struct bpf_object *obj;
        __u64 kcgid = 0, ucgid;
+       __u32 key = 0, pid;
        int exit_code = 1;
        char buf[256];
-       __u32 key = 0;
 
        err = setup_cgroup_environment();
        if (CHECK(err, "setup_cgroup_environment", "err %d errno %d\n", err,
@@ -81,6 +81,14 @@ int main(int argc, char **argv)
                  cgidmap_fd, errno))
                goto close_prog;
 
+       pidmap_fd = bpf_find_map(__func__, obj, "pidmap");
+       if (CHECK(pidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
+                 pidmap_fd, errno))
+               goto close_prog;
+
+       pid = getpid();
+       bpf_map_update_elem(pidmap_fd, &key, &pid, 0);
+
        snprintf(buf, sizeof(buf),
                 "/sys/kernel/debug/tracing/events/%s/id", probe_name);
        efd = open(buf, O_RDONLY, 0);
index 7cb1d74057ce0421f9659231f50c85a9aa8f156a..2ecd27b670d77e29e817d607ac80fd100c683884 100644 (file)
@@ -8647,7 +8647,7 @@ static struct bpf_test tests[] = {
                                    offsetof(struct __sk_buff, mark)),
                        BPF_EXIT_INSN(),
                },
-               .errstr = "dereference of modified ctx ptr R1 off=68+8, ctx+const is allowed, ctx+const+const is not",
+               .errstr = "dereference of modified ctx ptr",
                .result = REJECT,
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
        },
@@ -12258,6 +12258,62 @@ static struct bpf_test tests[] = {
                .result = ACCEPT,
                .retval = 5,
        },
+       {
+               "pass unmodified ctx pointer to helper",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_update),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .result = ACCEPT,
+       },
+       {
+               "pass modified ctx pointer to helper, 1",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_update),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .result = REJECT,
+               .errstr = "dereference of modified ctx ptr",
+       },
+       {
+               "pass modified ctx pointer to helper, 2",
+               .insns = {
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_get_socket_cookie),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .result_unpriv = REJECT,
+               .result = REJECT,
+               .errstr_unpriv = "dereference of modified ctx ptr",
+               .errstr = "dereference of modified ctx ptr",
+       },
+       {
+               "pass modified ctx pointer to helper, 3",
+               .insns = {
+                       BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 0),
+                       BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 4),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+                                    BPF_FUNC_csum_update),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .result = REJECT,
+               .errstr = "variable ctx access var_off=(0x0; 0x4)",
+       },
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)