public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Daniel Borkmann <daniel@iogearbox.net>,
	Martin KaFai Lau <kafai@fb.com>,
	Alexei Starovoitov <ast@kernel.org>,
	Alessio Balsini <balsini@android.com>,
	Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Subject: [PATCH 4.14 38/69] bpf: fix truncated jump targets on heavy expansions
Date: Mon,  7 Feb 2022 12:06:00 +0100	[thread overview]
Message-ID: <20220207103756.875238153@linuxfoundation.org> (raw)
In-Reply-To: <20220207103755.604121441@linuxfoundation.org>

From: Daniel Borkmann <daniel@iogearbox.net>

commit 050fad7c4534c13c8eb1d9c2ba66012e014773cb upstream.

Recently during testing, I ran into the following panic:

  [  207.892422] Internal error: Accessing user space memory outside uaccess.h routines: 96000004 [#1] SMP
  [  207.901637] Modules linked in: binfmt_misc [...]
  [  207.966530] CPU: 45 PID: 2256 Comm: test_verifier Tainted: G        W         4.17.0-rc3+ #7
  [  207.974956] Hardware name: FOXCONN R2-1221R-A4/C2U4N_MB, BIOS G31FB18A 03/31/2017
  [  207.982428] pstate: 60400005 (nZCv daif +PAN -UAO)
  [  207.987214] pc : bpf_skb_load_helper_8_no_cache+0x34/0xc0
  [  207.992603] lr : 0xffff000000bdb754
  [  207.996080] sp : ffff000013703ca0
  [  207.999384] x29: ffff000013703ca0 x28: 0000000000000001
  [  208.004688] x27: 0000000000000001 x26: 0000000000000000
  [  208.009992] x25: ffff000013703ce0 x24: ffff800fb4afcb00
  [  208.015295] x23: ffff00007d2f5038 x22: ffff00007d2f5000
  [  208.020599] x21: fffffffffeff2a6f x20: 000000000000000a
  [  208.025903] x19: ffff000009578000 x18: 0000000000000a03
  [  208.031206] x17: 0000000000000000 x16: 0000000000000000
  [  208.036510] x15: 0000ffff9de83000 x14: 0000000000000000
  [  208.041813] x13: 0000000000000000 x12: 0000000000000000
  [  208.047116] x11: 0000000000000001 x10: ffff0000089e7f18
  [  208.052419] x9 : fffffffffeff2a6f x8 : 0000000000000000
  [  208.057723] x7 : 000000000000000a x6 : 00280c6160000000
  [  208.063026] x5 : 0000000000000018 x4 : 0000000000007db6
  [  208.068329] x3 : 000000000008647a x2 : 19868179b1484500
  [  208.073632] x1 : 0000000000000000 x0 : ffff000009578c08
  [  208.078938] Process test_verifier (pid: 2256, stack limit = 0x0000000049ca7974)
  [  208.086235] Call trace:
  [  208.088672]  bpf_skb_load_helper_8_no_cache+0x34/0xc0
  [  208.093713]  0xffff000000bdb754
  [  208.096845]  bpf_test_run+0x78/0xf8
  [  208.100324]  bpf_prog_test_run_skb+0x148/0x230
  [  208.104758]  sys_bpf+0x314/0x1198
  [  208.108064]  el0_svc_naked+0x30/0x34
  [  208.111632] Code: 91302260 f9400001 f9001fa1 d2800001 (29500680)
  [  208.117717] ---[ end trace 263cb8a59b5bf29f ]---

The program itself which caused this had a long jump over the whole
instruction sequence where all of the inner instructions required
heavy expansions into multiple BPF instructions. Additionally, I also
had BPF hardening enabled which requires once more rewrites of all
constant values in order to blind them. Each time we rewrite insns,
bpf_adj_branches() would need to potentially adjust branch targets
which cross the patchlet boundary to accommodate for the additional
delta. Eventually that lead to the case where the target offset could
not fit into insn->off's upper 0x7fff limit anymore where then offset
wraps around becoming negative (in s16 universe), or vice versa
depending on the jump direction.

Therefore it becomes necessary to detect and reject any such occasions
in a generic way for native eBPF and cBPF to eBPF migrations. For
the latter we can simply check bounds in the bpf_convert_filter()'s
BPF_EMIT_JMP helper macro and bail out once we surpass limits. The
bpf_patch_insn_single() for native eBPF (and cBPF to eBPF in case
of subsequent hardening) is a bit more complex in that we need to
detect such truncations before hitting the bpf_prog_realloc(). Thus
the latter is split into an extra pass to probe problematic offsets
on the original program in order to fail early. With that in place
and carefully tested I no longer hit the panic and the rewrites are
rejected properly. The above example panic I've seen on bpf-next,
though the issue itself is generic in that a guard against this issue
in bpf seems more appropriate in this case.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
[ab: Dropped BPF_PSEUDO_CALL hardening, introoduced in 4.16]
Signed-off-by: Alessio Balsini <balsini@android.com>
Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/bpf/core.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++--------
 net/core/filter.c |   11 ++++++++--
 2 files changed, 60 insertions(+), 10 deletions(-)

--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -228,27 +228,57 @@ static bool bpf_is_jmp_and_has_target(co
 	       BPF_OP(insn->code) != BPF_EXIT;
 }
 
-static void bpf_adj_branches(struct bpf_prog *prog, u32 pos, u32 delta)
+static int bpf_adj_delta_to_off(struct bpf_insn *insn, u32 pos, u32 delta,
+				u32 curr, const bool probe_pass)
 {
+	const s32 off_min = S16_MIN, off_max = S16_MAX;
+	s32 off = insn->off;
+
+	if (curr < pos && curr + off + 1 > pos)
+		off += delta;
+	else if (curr > pos + delta && curr + off + 1 <= pos + delta)
+		off -= delta;
+	if (off < off_min || off > off_max)
+		return -ERANGE;
+	if (!probe_pass)
+		insn->off = off;
+	return 0;
+}
+
+static int bpf_adj_branches(struct bpf_prog *prog, u32 pos, u32 delta,
+			    const bool probe_pass)
+{
+	u32 i, insn_cnt = prog->len + (probe_pass ? delta : 0);
 	struct bpf_insn *insn = prog->insnsi;
-	u32 i, insn_cnt = prog->len;
+	int ret = 0;
 
 	for (i = 0; i < insn_cnt; i++, insn++) {
+		/* In the probing pass we still operate on the original,
+		 * unpatched image in order to check overflows before we
+		 * do any other adjustments. Therefore skip the patchlet.
+		 */
+		if (probe_pass && i == pos) {
+			i += delta + 1;
+			insn++;
+		}
+
 		if (!bpf_is_jmp_and_has_target(insn))
 			continue;
 
-		/* Adjust offset of jmps if we cross boundaries. */
-		if (i < pos && i + insn->off + 1 > pos)
-			insn->off += delta;
-		else if (i > pos + delta && i + insn->off + 1 <= pos + delta)
-			insn->off -= delta;
+		/* Adjust offset of jmps if we cross patch boundaries. */
+		ret = bpf_adj_delta_to_off(insn, pos, delta, i, probe_pass);
+		if (ret)
+			break;
 	}
+
+	return ret;
 }
 
 struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
 				       const struct bpf_insn *patch, u32 len)
 {
 	u32 insn_adj_cnt, insn_rest, insn_delta = len - 1;
+	const u32 cnt_max = S16_MAX;
 	struct bpf_prog *prog_adj;
 
 	/* Since our patchlet doesn't expand the image, we're done. */
@@ -259,6 +289,15 @@ struct bpf_prog *bpf_patch_insn_single(s
 
 	insn_adj_cnt = prog->len + insn_delta;
 
+	/* Reject anything that would potentially let the insn->off
+	 * target overflow when we have excessive program expansions.
+	 * We need to probe here before we do any reallocation where
+	 * we afterwards may not fail anymore.
+	 */
+	if (insn_adj_cnt > cnt_max &&
+	    bpf_adj_branches(prog, off, insn_delta, true))
+		return NULL;
+
 	/* Several new instructions need to be inserted. Make room
 	 * for them. Likely, there's no need for a new allocation as
 	 * last page could have large enough tailroom.
@@ -284,7 +323,11 @@ struct bpf_prog *bpf_patch_insn_single(s
 		sizeof(*patch) * insn_rest);
 	memcpy(prog_adj->insnsi + off, patch, sizeof(*patch) * len);
 
-	bpf_adj_branches(prog_adj, off, insn_delta);
+	/* We are guaranteed to not fail at this point, otherwise
+	 * the ship has sailed to reverse to the original state. An
+	 * overflow cannot happen at this point.
+	 */
+	BUG_ON(bpf_adj_branches(prog_adj, off, insn_delta, false));
 
 	return prog_adj;
 }
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -472,11 +472,18 @@ do_pass:
 
 #define BPF_EMIT_JMP							\
 	do {								\
+		const s32 off_min = S16_MIN, off_max = S16_MAX;		\
+		s32 off;						\
+									\
 		if (target >= len || target < 0)			\
 			goto err;					\
-		insn->off = addrs ? addrs[target] - addrs[i] - 1 : 0;	\
+		off = addrs ? addrs[target] - addrs[i] - 1 : 0;		\
 		/* Adjust pc relative offset for 2nd or 3rd insn. */	\
-		insn->off -= insn - tmp_insns;				\
+		off -= insn - tmp_insns;				\
+		/* Reject anything not fitting into insn->off. */	\
+		if (off < off_min || off > off_max)			\
+			goto err;					\
+		insn->off = off;					\
 	} while (0)
 
 		case BPF_JMP | BPF_JA:



  parent reply	other threads:[~2022-02-07 11:19 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-07 11:05 [PATCH 4.14 00/69] 4.14.265-rc1 review Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 01/69] Bluetooth: refactor malicious adv data check Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 02/69] s390/hypfs: include z/VM guests with access control group set Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 03/69] scsi: zfcp: Fix failed recovery on gone remote port with non-NPIV FCP devices Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 04/69] udf: Restore i_lenAlloc when inode expansion fails Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 05/69] udf: Fix NULL ptr deref when converting from inline format Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 06/69] PM: wakeup: simplify the output logic of pm_show_wakelocks() Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 07/69] netfilter: nft_payload: do not update layer 4 checksum when mangling fragments Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 08/69] serial: stm32: fix software flow control transfer Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 09/69] tty: n_gsm: fix SW flow control encoding/handling Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 10/69] tty: Add support for Brainboxes UC cards Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 11/69] usb-storage: Add unusual-devs entry for VL817 USB-SATA bridge Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 12/69] usb: common: ulpi: Fix crash in ulpi_match() Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 13/69] usb: gadget: f_sourcesink: Fix isoc transfer for USB_SPEED_SUPER_PLUS Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 14/69] USB: core: Fix hang in usb_kill_urb by adding memory barriers Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 15/69] usb: typec: tcpm: Do not disconnect while receiving VBUS off Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 16/69] net: sfp: ignore disabled SFP node Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 17/69] powerpc/32: Fix boot failure with GCC latent entropy plugin Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 18/69] lkdtm: Fix content of section containing lkdtm_rodata_do_nothing() Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 19/69] i40e: Increase delay to 1 s after global EMP reset Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 20/69] i40e: fix unsigned stat widths Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 21/69] rpmsg: char: Fix race between the release of rpmsg_ctrldev and cdev Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 22/69] rpmsg: char: Fix race between the release of rpmsg_eptdev " Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 23/69] scsi: bnx2fc: Flush destroy_work queue before calling bnx2fc_interface_put() Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 24/69] ipv6_tunnel: Rate limit warning messages Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 25/69] net: fix information leakage in /proc/net/ptype Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 26/69] ping: fix the sk_bound_dev_if match in ping_lookup Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 27/69] ipv4: avoid using shared IP generator for connected sockets Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 28/69] hwmon: (lm90) Reduce maximum conversion rate for G781 Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 29/69] NFSv4: Handle case where the lookup of a directory fails Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 30/69] NFSv4: nfs_atomic_open() can race when looking up a non-regular file Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 31/69] net-procfs: show net devices bound packet types Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 32/69] drm/msm: Fix wrong size calculation Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 33/69] drm/msm/dsi: invalid parameter check in msm_dsi_phy_enable Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 34/69] ibmvnic: dont spin in tasklet Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 35/69] yam: fix a memory leak in yam_siocdevprivate() Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 36/69] ipv4: raw: lock the socket in raw_bind() Greg Kroah-Hartman
2022-02-07 11:05 ` [PATCH 4.14 37/69] ipv4: tcp: send zero IPID in SYNACK messages Greg Kroah-Hartman
2022-02-07 11:06 ` Greg Kroah-Hartman [this message]
2022-02-07 11:06 ` [PATCH 4.14 39/69] netfilter: nat: remove l4 protocol port rovers Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 40/69] netfilter: nat: limit port clash resolution attempts Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 41/69] ipheth: fix EOVERFLOW in ipheth_rcvbulk_callback Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 42/69] net: amd-xgbe: ensure to reset the tx_timer_active flag Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 43/69] net: amd-xgbe: Fix skb data length underflow Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 44/69] rtnetlink: make sure to refresh master_dev/m_ops in __rtnl_newlink() Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 45/69] af_packet: fix data-race in packet_setsockopt / packet_setsockopt Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 46/69] audit: improve audit queue handling when "audit=1" on cmdline Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 47/69] ASoC: ops: Reject out of bounds values in snd_soc_put_volsw() Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 48/69] ASoC: ops: Reject out of bounds values in snd_soc_put_volsw_sx() Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 49/69] ASoC: ops: Reject out of bounds values in snd_soc_put_xr_sx() Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 50/69] drm/nouveau: fix off by one in BIOS boundary checking Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 51/69] block: bio-integrity: Advance seed correctly for larger interval sizes Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 52/69] RDMA/mlx4: Dont continue event handler after memory allocation failure Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 53/69] iommu/vt-d: Fix potential memory leak in intel_setup_irq_remapping() Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 54/69] iommu/amd: Fix loop timeout issue in iommu_ga_log_enable() Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 55/69] spi: bcm-qspi: check for valid cs before applying chip select Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 56/69] spi: mediatek: Avoid NULL pointer crash in interrupt Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 57/69] spi: meson-spicc: add IRQ check in meson_spicc_probe Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 58/69] net: ieee802154: ca8210: Stop leaking skbs Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 59/69] net: ieee802154: Return meaningful error codes from the netlink helpers Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 60/69] net: macsec: Verify that send_sci is on when setting Tx sci explicitly Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 61/69] drm/i915/overlay: Prevent divide by zero bugs in scaling Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 62/69] ASoC: fsl: Add missing error handling in pcm030_fabric_probe Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 63/69] scsi: bnx2fc: Make bnx2fc_recv_frame() mp safe Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 64/69] nfsd: nfsd4_setclientid_confirm mistakenly expires confirmed client Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 65/69] selftests: futex: Use variable MAKE instead of make Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 66/69] rtc: cmos: Evaluate century appropriate Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 67/69] EDAC/altera: Fix deferred probing Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 68/69] EDAC/xgene: " Greg Kroah-Hartman
2022-02-07 11:06 ` [PATCH 4.14 69/69] ext4: fix error handling in ext4_restore_inline_data() Greg Kroah-Hartman
2022-02-07 22:20 ` [PATCH 4.14 00/69] 4.14.265-rc1 review Guenter Roeck
2022-02-08  1:45 ` Slade Watkins
2022-02-08  9:58 ` Naresh Kamboju

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220207103756.875238153@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=ast@kernel.org \
    --cc=balsini@android.com \
    --cc=cascardo@canonical.com \
    --cc=daniel@iogearbox.net \
    --cc=kafai@fb.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox