Commit 4de593fb authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull networking fixes from Jakub Kicinski:
 "Networking fixes, including fixes from mac80211, netfilter and bpf.

  Current release - regressions:

   - bpf, cgroup: assign cgroup in cgroup_sk_alloc when called from
     interrupt

   - mdio: revert mechanical patches which broke handling of optional
     resources

   - dev_addr_list: prevent address duplication

  Previous releases - regressions:

   - sctp: break out if skb_header_pointer returns NULL in sctp_rcv_ootb
     (NULL deref)

   - Revert "mac80211: do not use low data rates for data frames with no
     ack flag", fixing broadcast transmissions

   - mac80211: fix use-after-free in CCMP/GCMP RX

   - netfilter: include zone id in tuple hash again, minimize collisions

   - netfilter: nf_tables: unlink table before deleting it (race -> UAF)

   - netfilter: log: work around missing softdep backend module

   - mptcp: don't return sockets in foreign netns

   - sched: flower: protect fl_walk() with rcu (race -> UAF)

   - ixgbe: fix NULL pointer dereference in ixgbe_xdp_setup

   - smsc95xx: fix stalled rx after link change

   - enetc: fix the incorrect clearing of IF_MODE bits

   - ipv4: fix rtnexthop len when RTA_FLOW is present

   - dsa: mv88e6xxx: 6161: use correct MAX MTU config method for this
     SKU

   - e100: fix length calculation & buffer overrun in ethtool::get_regs

  Previous releases - always broken:

   - mac80211: fix using stale frag_tail skb pointer in A-MSDU tx

   - mac80211: drop frames from invalid MAC address in ad-hoc mode

   - af_unix: fix races in sk_peer_pid and sk_peer_cred accesses (race
     -> UAF)

   - bpf, x86: Fix bpf mapping of atomic fetch implementation

   - bpf: handle return value of BPF_PROG_TYPE_STRUCT_OPS prog

   - netfilter: ip6_tables: zero-initialize fragment offset

   - mhi: fix error path in mhi_net_newlink

   - af_unix: return errno instead of NULL in unix_create1() when over
     the fs.file-max limit

  Misc:

   - bpf: exempt CAP_BPF from checks against bpf_jit_limit

   - netfilter: conntrack: make max chain length random, prevent
     guessing buckets by attackers

   - netfilter: nf_nat_masquerade: make async masq_inet6_event handling
     generic, defer conntrack walk to work queue (prevent hogging RTNL
     lock)"

* tag 'net-5.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (77 commits)
  af_unix: fix races in sk_peer_pid and sk_peer_cred accesses
  net: stmmac: fix EEE init issue when paired with EEE capable PHYs
  net: dev_addr_list: handle first address in __hw_addr_add_ex
  net: sched: flower: protect fl_walk() with rcu
  net: introduce and use lock_sock_fast_nested()
  net: phy: bcm7xxx: Fixed indirect MMD operations
  net: hns3: disable firmware compatible features when uninstall PF
  net: hns3: fix always enable rx vlan filter problem after selftest
  net: hns3: PF enable promisc for VF when mac table is overflow
  net: hns3: fix show wrong state when add existing uc mac address
  net: hns3: fix mixed flag HCLGE_FLAG_MQPRIO_ENABLE and HCLGE_FLAG_DCB_ENABLE
  net: hns3: don't rollback when destroy mqprio fail
  net: hns3: remove tc enable checking
  net: hns3: do not allow call hns3_nic_net_open repeatedly
  ixgbe: Fix NULL pointer dereference in ixgbe_xdp_setup
  net: bridge: mcast: Associate the seqcount with its protecting lock.
  net: mdio-ipq4019: Fix the error for an optional regs resource
  net: hns3: fix hclge_dbg_dump_tm_pg() stack usage
  net: mdio: mscc-miim: Fix the mdio controller
  af_unix: Return errno instead of NULL in unix_create1().
  ...
parents 115f6134 35306eb2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3384,9 +3384,11 @@ F: Documentation/networking/filter.rst
F:	Documentation/userspace-api/ebpf/
F:	arch/*/net/*
F:	include/linux/bpf*
F:	include/linux/btf*
F:	include/linux/filter.h
F:	include/trace/events/xdp.h
F:	include/uapi/linux/bpf*
F:	include/uapi/linux/btf*
F:	include/uapi/linux/filter.h
F:	kernel/bpf/
F:	kernel/trace/bpf_trace.c
+43 −14
Original line number Diff line number Diff line
@@ -662,6 +662,11 @@ static void build_epilogue(struct jit_ctx *ctx)
	((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative : func) : \
	 func##_positive)

static bool is_bad_offset(int b_off)
{
	return b_off > 0x1ffff || b_off < -0x20000;
}

static int build_body(struct jit_ctx *ctx)
{
	const struct bpf_prog *prog = ctx->skf;
@@ -728,7 +733,10 @@ static int build_body(struct jit_ctx *ctx)
			/* Load return register on DS for failures */
			emit_reg_move(r_ret, r_zero, ctx);
			/* Return with error */
			emit_b(b_imm(prog->len, ctx), ctx);
			b_off = b_imm(prog->len, ctx);
			if (is_bad_offset(b_off))
				return -E2BIG;
			emit_b(b_off, ctx);
			emit_nop(ctx);
			break;
		case BPF_LD | BPF_W | BPF_IND:
@@ -775,8 +783,10 @@ static int build_body(struct jit_ctx *ctx)
			emit_jalr(MIPS_R_RA, r_s0, ctx);
			emit_reg_move(MIPS_R_A0, r_skb, ctx); /* delay slot */
			/* Check the error value */
			emit_bcond(MIPS_COND_NE, r_ret, 0,
				   b_imm(prog->len, ctx), ctx);
			b_off = b_imm(prog->len, ctx);
			if (is_bad_offset(b_off))
				return -E2BIG;
			emit_bcond(MIPS_COND_NE, r_ret, 0, b_off, ctx);
			emit_reg_move(r_ret, r_zero, ctx);
			/* We are good */
			/* X <- P[1:K] & 0xf */
@@ -855,8 +865,10 @@ static int build_body(struct jit_ctx *ctx)
			/* A /= X */
			ctx->flags |= SEEN_X | SEEN_A;
			/* Check if r_X is zero */
			emit_bcond(MIPS_COND_EQ, r_X, r_zero,
				   b_imm(prog->len, ctx), ctx);
			b_off = b_imm(prog->len, ctx);
			if (is_bad_offset(b_off))
				return -E2BIG;
			emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_off, ctx);
			emit_load_imm(r_ret, 0, ctx); /* delay slot */
			emit_div(r_A, r_X, ctx);
			break;
@@ -864,8 +876,10 @@ static int build_body(struct jit_ctx *ctx)
			/* A %= X */
			ctx->flags |= SEEN_X | SEEN_A;
			/* Check if r_X is zero */
			emit_bcond(MIPS_COND_EQ, r_X, r_zero,
				   b_imm(prog->len, ctx), ctx);
			b_off = b_imm(prog->len, ctx);
			if (is_bad_offset(b_off))
				return -E2BIG;
			emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_off, ctx);
			emit_load_imm(r_ret, 0, ctx); /* delay slot */
			emit_mod(r_A, r_X, ctx);
			break;
@@ -926,7 +940,10 @@ static int build_body(struct jit_ctx *ctx)
			break;
		case BPF_JMP | BPF_JA:
			/* pc += K */
			emit_b(b_imm(i + k + 1, ctx), ctx);
			b_off = b_imm(i + k + 1, ctx);
			if (is_bad_offset(b_off))
				return -E2BIG;
			emit_b(b_off, ctx);
			emit_nop(ctx);
			break;
		case BPF_JMP | BPF_JEQ | BPF_K:
@@ -1056,12 +1073,16 @@ static int build_body(struct jit_ctx *ctx)
			break;
		case BPF_RET | BPF_A:
			ctx->flags |= SEEN_A;
			if (i != prog->len - 1)
			if (i != prog->len - 1) {
				/*
				 * If this is not the last instruction
				 * then jump to the epilogue
				 */
				emit_b(b_imm(prog->len, ctx), ctx);
				b_off = b_imm(prog->len, ctx);
				if (is_bad_offset(b_off))
					return -E2BIG;
				emit_b(b_off, ctx);
			}
			emit_reg_move(r_ret, r_A, ctx); /* delay slot */
			break;
		case BPF_RET | BPF_K:
@@ -1075,7 +1096,10 @@ static int build_body(struct jit_ctx *ctx)
				 * If this is not the last instruction
				 * then jump to the epilogue
				 */
				emit_b(b_imm(prog->len, ctx), ctx);
				b_off = b_imm(prog->len, ctx);
				if (is_bad_offset(b_off))
					return -E2BIG;
				emit_b(b_off, ctx);
				emit_nop(ctx);
			}
			break;
@@ -1133,8 +1157,10 @@ static int build_body(struct jit_ctx *ctx)
			/* Load *dev pointer */
			emit_load_ptr(r_s0, r_skb, off, ctx);
			/* error (0) in the delay slot */
			emit_bcond(MIPS_COND_EQ, r_s0, r_zero,
				   b_imm(prog->len, ctx), ctx);
			b_off = b_imm(prog->len, ctx);
			if (is_bad_offset(b_off))
				return -E2BIG;
			emit_bcond(MIPS_COND_EQ, r_s0, r_zero, b_off, ctx);
			emit_reg_move(r_ret, r_zero, ctx);
			if (code == (BPF_ANC | SKF_AD_IFINDEX)) {
				BUILD_BUG_ON(sizeof_field(struct net_device, ifindex) != 4);
@@ -1244,7 +1270,10 @@ void bpf_jit_compile(struct bpf_prog *fp)

	/* Generate the actual JIT code */
	build_prologue(&ctx);
	build_body(&ctx);
	if (build_body(&ctx)) {
		module_memfree(ctx.target);
		goto out;
	}
	build_epilogue(&ctx);

	/* Update the icache */
+48 −18
Original line number Diff line number Diff line
@@ -1341,9 +1341,10 @@ st: if (is_imm8(insn->off))
			if (insn->imm == (BPF_AND | BPF_FETCH) ||
			    insn->imm == (BPF_OR | BPF_FETCH) ||
			    insn->imm == (BPF_XOR | BPF_FETCH)) {
				u8 *branch_target;
				bool is64 = BPF_SIZE(insn->code) == BPF_DW;
				u32 real_src_reg = src_reg;
				u32 real_dst_reg = dst_reg;
				u8 *branch_target;

				/*
				 * Can't be implemented with a single x86 insn.
@@ -1354,11 +1355,13 @@ st: if (is_imm8(insn->off))
				emit_mov_reg(&prog, true, BPF_REG_AX, BPF_REG_0);
				if (src_reg == BPF_REG_0)
					real_src_reg = BPF_REG_AX;
				if (dst_reg == BPF_REG_0)
					real_dst_reg = BPF_REG_AX;

				branch_target = prog;
				/* Load old value */
				emit_ldx(&prog, BPF_SIZE(insn->code),
					 BPF_REG_0, dst_reg, insn->off);
					 BPF_REG_0, real_dst_reg, insn->off);
				/*
				 * Perform the (commutative) operation locally,
				 * put the result in the AUX_REG.
@@ -1369,7 +1372,8 @@ st: if (is_imm8(insn->off))
				      add_2reg(0xC0, AUX_REG, real_src_reg));
				/* Attempt to swap in new value */
				err = emit_atomic(&prog, BPF_CMPXCHG,
						  dst_reg, AUX_REG, insn->off,
						  real_dst_reg, AUX_REG,
						  insn->off,
						  BPF_SIZE(insn->code));
				if (WARN_ON(err))
					return err;
@@ -1383,7 +1387,6 @@ st: if (is_imm8(insn->off))
				/* Restore R0 after clobbering RAX */
				emit_mov_reg(&prog, true, BPF_REG_0, BPF_REG_AX);
				break;

			}

			err = emit_atomic(&prog, insn->imm, dst_reg, src_reg,
@@ -1744,7 +1747,7 @@ static void restore_regs(const struct btf_func_model *m, u8 **prog, int nr_args,
}

static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
			   struct bpf_prog *p, int stack_size, bool mod_ret)
			   struct bpf_prog *p, int stack_size, bool save_ret)
{
	u8 *prog = *pprog;
	u8 *jmp_insn;
@@ -1777,11 +1780,15 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog,
	if (emit_call(&prog, p->bpf_func, prog))
		return -EINVAL;

	/* BPF_TRAMP_MODIFY_RETURN trampolines can modify the return
	/*
	 * BPF_TRAMP_MODIFY_RETURN trampolines can modify the return
	 * of the previous call which is then passed on the stack to
	 * the next BPF program.
	 *
	 * BPF_TRAMP_FENTRY trampoline may need to return the return
	 * value of BPF_PROG_TYPE_STRUCT_OPS prog.
	 */
	if (mod_ret)
	if (save_ret)
		emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8);

	/* replace 2 nops with JE insn, since jmp target is known */
@@ -1828,13 +1835,15 @@ static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond)
}

static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
		      struct bpf_tramp_progs *tp, int stack_size)
		      struct bpf_tramp_progs *tp, int stack_size,
		      bool save_ret)
{
	int i;
	u8 *prog = *pprog;

	for (i = 0; i < tp->nr_progs; i++) {
		if (invoke_bpf_prog(m, &prog, tp->progs[i], stack_size, false))
		if (invoke_bpf_prog(m, &prog, tp->progs[i], stack_size,
				    save_ret))
			return -EINVAL;
	}
	*pprog = prog;
@@ -1877,6 +1886,23 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
	return 0;
}

static bool is_valid_bpf_tramp_flags(unsigned int flags)
{
	if ((flags & BPF_TRAMP_F_RESTORE_REGS) &&
	    (flags & BPF_TRAMP_F_SKIP_FRAME))
		return false;

	/*
	 * BPF_TRAMP_F_RET_FENTRY_RET is only used by bpf_struct_ops,
	 * and it must be used alone.
	 */
	if ((flags & BPF_TRAMP_F_RET_FENTRY_RET) &&
	    (flags & ~BPF_TRAMP_F_RET_FENTRY_RET))
		return false;

	return true;
}

/* Example:
 * __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
 * its 'struct btf_func_model' will be nr_args=2
@@ -1949,17 +1975,19 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
	struct bpf_tramp_progs *fmod_ret = &tprogs[BPF_TRAMP_MODIFY_RETURN];
	u8 **branches = NULL;
	u8 *prog;
	bool save_ret;

	/* x86-64 supports up to 6 arguments. 7+ can be added in the future */
	if (nr_args > 6)
		return -ENOTSUPP;

	if ((flags & BPF_TRAMP_F_RESTORE_REGS) &&
	    (flags & BPF_TRAMP_F_SKIP_FRAME))
	if (!is_valid_bpf_tramp_flags(flags))
		return -EINVAL;

	if (flags & BPF_TRAMP_F_CALL_ORIG)
		stack_size += 8; /* room for return value of orig_call */
	/* room for return value of orig_call or fentry prog */
	save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
	if (save_ret)
		stack_size += 8;

	if (flags & BPF_TRAMP_F_IP_ARG)
		stack_size += 8; /* room for IP address argument */
@@ -2005,7 +2033,8 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
	}

	if (fentry->nr_progs)
		if (invoke_bpf(m, &prog, fentry, stack_size))
		if (invoke_bpf(m, &prog, fentry, stack_size,
			       flags & BPF_TRAMP_F_RET_FENTRY_RET))
			return -EINVAL;

	if (fmod_ret->nr_progs) {
@@ -2052,7 +2081,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
	}

	if (fexit->nr_progs)
		if (invoke_bpf(m, &prog, fexit, stack_size)) {
		if (invoke_bpf(m, &prog, fexit, stack_size, false)) {
			ret = -EINVAL;
			goto cleanup;
		}
@@ -2072,9 +2101,10 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
			ret = -EINVAL;
			goto cleanup;
		}
		/* restore original return value back into RAX */
		emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8);
	}
	/* restore return value of orig_call or fentry prog back into RAX */
	if (save_ret)
		emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8);

	EMIT1(0x5B); /* pop rbx */
	EMIT1(0xC9); /* leave */
+10 −7
Original line number Diff line number Diff line
@@ -2834,8 +2834,8 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
	if (err)
		return err;

	/* Port Control 2: don't force a good FCS, set the maximum frame size to
	 * 10240 bytes, disable 802.1q tags checking, don't discard tagged or
	/* Port Control 2: don't force a good FCS, set the MTU size to
	 * 10222 bytes, disable 802.1q tags checking, don't discard tagged or
	 * untagged frames on this port, do a destination address lookup on all
	 * received packets as usual, disable ARP mirroring and don't send a
	 * copy of all transmitted/received frames on this port to the CPU.
@@ -2854,7 +2854,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
		return err;

	if (chip->info->ops->port_set_jumbo_size) {
		err = chip->info->ops->port_set_jumbo_size(chip, port, 10240);
		err = chip->info->ops->port_set_jumbo_size(chip, port, 10218);
		if (err)
			return err;
	}
@@ -2944,10 +2944,10 @@ static int mv88e6xxx_get_max_mtu(struct dsa_switch *ds, int port)
	struct mv88e6xxx_chip *chip = ds->priv;

	if (chip->info->ops->port_set_jumbo_size)
		return 10240;
		return 10240 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
	else if (chip->info->ops->set_max_frame_size)
		return 1632;
	return 1522;
		return 1632 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
	return 1522 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
}

static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
@@ -2955,6 +2955,9 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
	struct mv88e6xxx_chip *chip = ds->priv;
	int ret = 0;

	if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
		new_mtu += EDSA_HLEN;

	mv88e6xxx_reg_lock(chip);
	if (chip->info->ops->port_set_jumbo_size)
		ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu);
@@ -3725,7 +3728,6 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
	.port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
	.port_set_mcast_flood = mv88e6352_port_set_mcast_flood,
	.port_set_ether_type = mv88e6351_port_set_ether_type,
	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
	.port_pause_limit = mv88e6097_port_pause_limit,
	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
@@ -3750,6 +3752,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
	.avb_ops = &mv88e6165_avb_ops,
	.ptp_ops = &mv88e6165_ptp_ops,
	.phylink_validate = mv88e6185_phylink_validate,
	.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
};

static const struct mv88e6xxx_ops mv88e6165_ops = {
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/timecounter.h>
#include <net/dsa.h>

#define EDSA_HLEN		8
#define MV88E6XXX_N_FID		4096

/* PVT limits for 4-bit port and 5-bit switch */
Loading