Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ead68f21 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull networking fixes from David Miller"
 "What's a holiday weekend without some networking bug fixes? [1]

   1) Fix some eBPF JIT bugs wrt. SKB pointers across helper function
      calls, from Daniel Borkmann.

   2) Fix regression from errata limiting change to marvell PHY driver,
      from Zhao Qiang.

   3) Fix u16 overflow in SCTP, from Xin Long.

   4) Fix potential memory leak during bridge newlink, from Nikolay
      Aleksandrov.

   5) Fix BPF selftest build on s390, from Hendrik Brueckner.

   6) Don't append to cfg80211 automatically generated certs file,
      always write new ones from scratch. From Thierry Reding.

   7) Fix sleep in atomic in mac80211 hwsim, from Jia-Ju Bai.

   8) Fix hang on tg3 MTU change with certain chips, from Brian King.

   9) Add stall detection to arc emac driver and reset chip when this
      happens, from Alexander Kochetkov.

  10) Fix MTU limitng in GRE tunnel drivers, from Xin Long.

  11) Fix stmmac timestamping bug due to mis-shifting of field. From
      Fredrik Hallenberg.

  12) Fix metrics match when deleting an ipv4 route. The kernel sets
      some internal metrics bits which the user isn't going to set when
      it makes the delete request. From Phil Sutter.

  13) mvneta driver loop over RX queues limits on "txq_number" :-) Fix
      from Yelena Krivosheev.

  14) Fix double free and memory corruption in get_net_ns_by_id, from
      Eric W. Biederman.

  15) Flush ipv4 FIB tables in the reverse order. Some tables can share
      their actual backing data, in particular this happens for the MAIN
      and LOCAL tables. We have to kill the LOCAL table first, because
      it uses MAIN's backing memory. Fix from Ido Schimmel.

  16) Several eBPF verifier value tracking fixes, from Edward Cree, Jann
      Horn, and Alexei Starovoitov.

  17) Make changes to ipv6 autoflowlabel sysctl really propagate to
      sockets, unless the socket has set the per-socket value
      explicitly. From Shaohua Li.

  18) Fix leaks and double callback invocations of zerocopy SKBs, from
      Willem de Bruijn"

[1] Is this a trick question? "Relaxing"? "Quiet"? "Fine"? - Linus.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (77 commits)
  skbuff: skb_copy_ubufs must release uarg even without user frags
  skbuff: orphan frags before zerocopy clone
  net: reevalulate autoflowlabel setting after sysctl setting
  openvswitch: Fix pop_vlan action for double tagged frames
  ipv6: Honor specified parameters in fibmatch lookup
  bpf: do not allow root to mangle valid pointers
  selftests/bpf: add tests for recent bugfixes
  bpf: fix integer overflows
  bpf: don't prune branches when a scalar is replaced with a pointer
  bpf: force strict alignment checks for stack pointers
  bpf: fix missing error return in check_stack_boundary()
  bpf: fix 32-bit ALU op verification
  bpf: fix incorrect tracking of register size truncation
  bpf: fix incorrect sign extension in check_alu_op()
  bpf/verifier: fix bounds calculation on BPF_RSH
  ipv4: Fix use-after-free when flushing FIB tables
  s390/qeth: fix error handling in checksum cmd callback
  tipc: remove joining group member from congested list
  selftests: net: Adding config fragment CONFIG_NUMA=y
  nfp: bpf: keep track of the offloaded program
  ...
parents 9035a896 c50b7c47
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -763,7 +763,8 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
			func = (u8 *) __bpf_call_base + imm;

			/* Save skb pointer if we need to re-cache skb data */
			if (bpf_helper_changes_pkt_data(func))
			if ((ctx->seen & SEEN_SKB) &&
			    bpf_helper_changes_pkt_data(func))
				PPC_BPF_STL(3, 1, bpf_jit_stack_local(ctx));

			bpf_jit_emit_func_call(image, ctx, (u64)func);
@@ -772,7 +773,8 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
			PPC_MR(b2p[BPF_REG_0], 3);

			/* refresh skb cache */
			if (bpf_helper_changes_pkt_data(func)) {
			if ((ctx->seen & SEEN_SKB) &&
			    bpf_helper_changes_pkt_data(func)) {
				/* reload skb pointer to r3 */
				PPC_BPF_LL(3, 1, bpf_jit_stack_local(ctx));
				bpf_jit_emit_skb_loads(image, ctx);
+5 −6
Original line number Diff line number Diff line
@@ -55,8 +55,7 @@ struct bpf_jit {
#define SEEN_LITERAL	8	/* code uses literals */
#define SEEN_FUNC	16	/* calls C functions */
#define SEEN_TAIL_CALL	32	/* code uses tail calls */
#define SEEN_SKB_CHANGE	64	/* code changes skb data */
#define SEEN_REG_AX	128	/* code uses constant blinding */
#define SEEN_REG_AX	64	/* code uses constant blinding */
#define SEEN_STACK	(SEEN_FUNC | SEEN_MEM | SEEN_SKB)

/*
@@ -448,13 +447,13 @@ static void bpf_jit_prologue(struct bpf_jit *jit, u32 stack_depth)
			EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0,
				      REG_15, 152);
	}
	if (jit->seen & SEEN_SKB)
	if (jit->seen & SEEN_SKB) {
		emit_load_skb_data_hlen(jit);
	if (jit->seen & SEEN_SKB_CHANGE)
		/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
		EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15,
			      STK_OFF_SKBP);
	}
}

/*
 * Function epilogue
@@ -983,8 +982,8 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
		EMIT2(0x0d00, REG_14, REG_W1);
		/* lgr %b0,%r2: load return value into %b0 */
		EMIT4(0xb9040000, BPF_REG_0, REG_2);
		if (bpf_helper_changes_pkt_data((void *)func)) {
			jit->seen |= SEEN_SKB_CHANGE;
		if ((jit->seen & SEEN_SKB) &&
		    bpf_helper_changes_pkt_data((void *)func)) {
			/* lg %b1,ST_OFF_SKBP(%r15) */
			EMIT6_DISP_LH(0xe3000000, 0x0004, BPF_REG_1, REG_0,
				      REG_15, STK_OFF_SKBP);
+4 −2
Original line number Diff line number Diff line
@@ -1245,14 +1245,16 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
		u8 *func = ((u8 *)__bpf_call_base) + imm;

		ctx->saw_call = true;
		if (ctx->saw_ld_abs_ind && bpf_helper_changes_pkt_data(func))
			emit_reg_move(bpf2sparc[BPF_REG_1], L7, ctx);

		emit_call((u32 *)func, ctx);
		emit_nop(ctx);

		emit_reg_move(O0, bpf2sparc[BPF_REG_0], ctx);

		if (bpf_helper_changes_pkt_data(func) && ctx->saw_ld_abs_ind)
			load_skb_regs(ctx, bpf2sparc[BPF_REG_6]);
		if (ctx->saw_ld_abs_ind && bpf_helper_changes_pkt_data(func))
			load_skb_regs(ctx, L7);
		break;
	}

+2 −0
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ struct arc_emac_priv {
	unsigned int link;
	unsigned int duplex;
	unsigned int speed;

	unsigned int rx_missed_errors;
};

/**
+142 −22
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@

#include "emac.h"

static void arc_emac_restart(struct net_device *ndev);

/**
 * arc_emac_tx_avail - Return the number of available slots in the tx ring.
 * @priv: Pointer to ARC EMAC private data structure.
@@ -210,39 +212,48 @@ static int arc_emac_rx(struct net_device *ndev, int budget)
			continue;
		}

		pktlen = info & LEN_MASK;
		stats->rx_packets++;
		stats->rx_bytes += pktlen;
		skb = rx_buff->skb;
		skb_put(skb, pktlen);
		skb->dev = ndev;
		skb->protocol = eth_type_trans(skb, ndev);

		dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr),
				 dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE);

		/* Prepare the BD for next cycle */
		rx_buff->skb = netdev_alloc_skb_ip_align(ndev,
							 EMAC_BUFFER_SIZE);
		if (unlikely(!rx_buff->skb)) {
		/* Prepare the BD for next cycle. netif_receive_skb()
		 * only if new skb was allocated and mapped to avoid holes
		 * in the RX fifo.
		 */
		skb = netdev_alloc_skb_ip_align(ndev, EMAC_BUFFER_SIZE);
		if (unlikely(!skb)) {
			if (net_ratelimit())
				netdev_err(ndev, "cannot allocate skb\n");
			/* Return ownership to EMAC */
			rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE);
			stats->rx_errors++;
			/* Because receive_skb is below, increment rx_dropped */
			stats->rx_dropped++;
			continue;
		}

		/* receive_skb only if new skb was allocated to avoid holes */
		netif_receive_skb(skb);

		addr = dma_map_single(&ndev->dev, (void *)rx_buff->skb->data,
		addr = dma_map_single(&ndev->dev, (void *)skb->data,
				      EMAC_BUFFER_SIZE, DMA_FROM_DEVICE);
		if (dma_mapping_error(&ndev->dev, addr)) {
			if (net_ratelimit())
				netdev_err(ndev, "cannot dma map\n");
			dev_kfree_skb(rx_buff->skb);
				netdev_err(ndev, "cannot map dma buffer\n");
			dev_kfree_skb(skb);
			/* Return ownership to EMAC */
			rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE);
			stats->rx_errors++;
			stats->rx_dropped++;
			continue;
		}

		/* unmap previosly mapped skb */
		dma_unmap_single(&ndev->dev, dma_unmap_addr(rx_buff, addr),
				 dma_unmap_len(rx_buff, len), DMA_FROM_DEVICE);

		pktlen = info & LEN_MASK;
		stats->rx_packets++;
		stats->rx_bytes += pktlen;
		skb_put(rx_buff->skb, pktlen);
		rx_buff->skb->dev = ndev;
		rx_buff->skb->protocol = eth_type_trans(rx_buff->skb, ndev);

		netif_receive_skb(rx_buff->skb);

		rx_buff->skb = skb;
		dma_unmap_addr_set(rx_buff, addr, addr);
		dma_unmap_len_set(rx_buff, len, EMAC_BUFFER_SIZE);

@@ -258,6 +269,53 @@ static int arc_emac_rx(struct net_device *ndev, int budget)
	return work_done;
}

/**
 * arc_emac_rx_miss_handle - handle R_MISS register
 * @ndev:	Pointer to the net_device structure.
 */
static void arc_emac_rx_miss_handle(struct net_device *ndev)
{
	struct arc_emac_priv *priv = netdev_priv(ndev);
	struct net_device_stats *stats = &ndev->stats;
	unsigned int miss;

	miss = arc_reg_get(priv, R_MISS);
	if (miss) {
		stats->rx_errors += miss;
		stats->rx_missed_errors += miss;
		priv->rx_missed_errors += miss;
	}
}

/**
 * arc_emac_rx_stall_check - check RX stall
 * @ndev:	Pointer to the net_device structure.
 * @budget:	How many BDs requested to process on 1 call.
 * @work_done:	How many BDs processed
 *
 * Under certain conditions EMAC stop reception of incoming packets and
 * continuously increment R_MISS register instead of saving data into
 * provided buffer. This function detect that condition and restart
 * EMAC.
 */
static void arc_emac_rx_stall_check(struct net_device *ndev,
				    int budget, unsigned int work_done)
{
	struct arc_emac_priv *priv = netdev_priv(ndev);
	struct arc_emac_bd *rxbd;

	if (work_done)
		priv->rx_missed_errors = 0;

	if (priv->rx_missed_errors && budget) {
		rxbd = &priv->rxbd[priv->last_rx_bd];
		if (le32_to_cpu(rxbd->info) & FOR_EMAC) {
			arc_emac_restart(ndev);
			priv->rx_missed_errors = 0;
		}
	}
}

/**
 * arc_emac_poll - NAPI poll handler.
 * @napi:	Pointer to napi_struct structure.
@@ -272,6 +330,7 @@ static int arc_emac_poll(struct napi_struct *napi, int budget)
	unsigned int work_done;

	arc_emac_tx_clean(ndev);
	arc_emac_rx_miss_handle(ndev);

	work_done = arc_emac_rx(ndev, budget);
	if (work_done < budget) {
@@ -279,6 +338,8 @@ static int arc_emac_poll(struct napi_struct *napi, int budget)
		arc_reg_or(priv, R_ENABLE, RXINT_MASK | TXINT_MASK);
	}

	arc_emac_rx_stall_check(ndev, budget, work_done);

	return work_done;
}

@@ -320,6 +381,8 @@ static irqreturn_t arc_emac_intr(int irq, void *dev_instance)
		if (status & MSER_MASK) {
			stats->rx_missed_errors += 0x100;
			stats->rx_errors += 0x100;
			priv->rx_missed_errors += 0x100;
			napi_schedule(&priv->napi);
		}

		if (status & RXCR_MASK) {
@@ -732,6 +795,63 @@ static int arc_emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}


/**
 * arc_emac_restart - Restart EMAC
 * @ndev:	Pointer to net_device structure.
 *
 * This function do hardware reset of EMAC in order to restore
 * network packets reception.
 */
static void arc_emac_restart(struct net_device *ndev)
{
	struct arc_emac_priv *priv = netdev_priv(ndev);
	struct net_device_stats *stats = &ndev->stats;
	int i;

	if (net_ratelimit())
		netdev_warn(ndev, "restarting stalled EMAC\n");

	netif_stop_queue(ndev);

	/* Disable interrupts */
	arc_reg_clr(priv, R_ENABLE, RXINT_MASK | TXINT_MASK | ERR_MASK);

	/* Disable EMAC */
	arc_reg_clr(priv, R_CTRL, EN_MASK);

	/* Return the sk_buff to system */
	arc_free_tx_queue(ndev);

	/* Clean Tx BD's */
	priv->txbd_curr = 0;
	priv->txbd_dirty = 0;
	memset(priv->txbd, 0, TX_RING_SZ);

	for (i = 0; i < RX_BD_NUM; i++) {
		struct arc_emac_bd *rxbd = &priv->rxbd[i];
		unsigned int info = le32_to_cpu(rxbd->info);

		if (!(info & FOR_EMAC)) {
			stats->rx_errors++;
			stats->rx_dropped++;
		}
		/* Return ownership to EMAC */
		rxbd->info = cpu_to_le32(FOR_EMAC | EMAC_BUFFER_SIZE);
	}
	priv->last_rx_bd = 0;

	/* Make sure info is visible to EMAC before enable */
	wmb();

	/* Enable interrupts */
	arc_reg_set(priv, R_ENABLE, RXINT_MASK | TXINT_MASK | ERR_MASK);

	/* Enable EMAC */
	arc_reg_or(priv, R_CTRL, EN_MASK);

	netif_start_queue(ndev);
}

static const struct net_device_ops arc_emac_netdev_ops = {
	.ndo_open		= arc_emac_open,
	.ndo_stop		= arc_emac_stop,
Loading