diff options
37 files changed, 301 insertions, 129 deletions
diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c index 9065047f844b..77e4ebc206ae 100644 --- a/arch/um/drivers/vector_transports.c +++ b/arch/um/drivers/vector_transports.c @@ -120,7 +120,8 @@ static int raw_form_header(uint8_t *header,  		skb,  		vheader,  		virtio_legacy_is_little_endian(), -		false +		false, +		0  	);  	return 0; diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 8a945c9341d6..98663c50ded0 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -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;  		} diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index a50e08bb4748..750007513f9d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -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; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index c8c74aa548d9..fb2c8f8071e6 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -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; diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index e28c0d2c58e9..cb5b0f58c395 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -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. diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c index 2414f1dc8ddd..72433f3efc74 100644 --- a/drivers/net/fddi/skfp/skfddi.c +++ b/drivers/net/fddi/skfp/skfddi.c @@ -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; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 1e9bde68698d..7b18a8c267c2 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -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 diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c index cd09c3af2117..6e8e42361fd5 100644 --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -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); diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 9b6cb780affe..f0f7cd977667 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -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) != diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 85e14adf5207..a192a017cc68 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -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", diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 90d07ed224d5..b0e8b9613054 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -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); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 2aaa18ec7d46..1619ee3070b6 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -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) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index f144216febc6..9397628a1967 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -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 && diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index c4f5caaf3778..f6a3543e5247 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -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) diff --git a/include/net/udp.h b/include/net/udp.h index 7ba0ed252c52..b1ea8b0f5e6a 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -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); diff --git a/include/uapi/linux/if_xdp.h b/include/uapi/linux/if_xdp.h index 1fa0e977ea8d..caed8b1614ff 100644 --- a/include/uapi/linux/if_xdp.h +++ b/include/uapi/linux/if_xdp.h @@ -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 { diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index ae00a3c49b8a..c9bf74b94f37 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -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 diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index d6403b5166f4..cced0c1e63e2 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -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, ®_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 diff --git a/kernel/umh.c b/kernel/umh.c index 30db93fd7e39..c449858946af 100644 --- a/kernel/umh.c +++ b/kernel/umh.c @@ -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;  		}  	}  } diff --git a/net/bpfilter/Makefile b/net/bpfilter/Makefile index aafa72001fcd..e0bbe7583e58 100644 --- a/net/bpfilter/Makefile +++ b/net/bpfilter/Makefile @@ -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 $< $@ diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c index b13d058f8c34..09522573f611 100644 --- a/net/bpfilter/bpfilter_kern.c +++ b/net/bpfilter/bpfilter_kern.c @@ -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); diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b19e3104afd6..502f66349530 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -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;  } diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 38d906baf1df..c4f5602308ed 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -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(); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2741953adaba..141acd92e58a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -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); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 3365362cac88..9bb27df4dac5 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -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), diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index d0390d844ac8..d9ad986c7b2c 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c @@ -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);  } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index a02ad100f0d7..2ee08b6a86a4 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -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, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 164afd31aebf..e6645cae403e 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -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;  } diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 7eef1cffbf1b..655187bed5d8 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c @@ -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); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 54ce66f68482..ee018564b2b4 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -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;  		} diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 9618b4a83cee..98c4afe7c15b 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -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) diff --git a/net/socket.c b/net/socket.c index af57d85bcb48..8a109012608a 100644 --- a/net/socket.c +++ b/net/socket.c @@ -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;  } diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 7eb4948a38d2..b9ef487c4618 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c @@ -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) diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index c6ed2454f7ce..36919a254ba3 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -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; diff --git a/tools/testing/selftests/bpf/get_cgroup_id_kern.c b/tools/testing/selftests/bpf/get_cgroup_id_kern.c index 2cf8cb23f209..014dba10b8a5 100644 --- a/tools/testing/selftests/bpf/get_cgroup_id_kern.c +++ b/tools/testing/selftests/bpf/get_cgroup_id_kern.c @@ -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(); diff --git a/tools/testing/selftests/bpf/get_cgroup_id_user.c b/tools/testing/selftests/bpf/get_cgroup_id_user.c index ea19a42e5894..e8da7b39158d 100644 --- a/tools/testing/selftests/bpf/get_cgroup_id_user.c +++ b/tools/testing/selftests/bpf/get_cgroup_id_user.c @@ -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); diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index 7cb1d74057ce..2ecd27b670d7 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c @@ -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)  | 
