diff --git a/danctnix-besser-pkgbuild/kernel/0021-bes2600-bounce-sdio-tx-buffers.patch b/danctnix-besser-pkgbuild/kernel/0021-bes2600-bounce-sdio-tx-buffers.patch new file mode 100644 index 000000000..0d17fbd24 --- /dev/null +++ b/danctnix-besser-pkgbuild/kernel/0021-bes2600-bounce-sdio-tx-buffers.patch @@ -0,0 +1,123 @@ +From 49d9b77a695dfa42d0c39e7c517829b2f7c15b1b Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +Date: Thu, 23 Apr 2026 11:58:31 +0200 +Subject: [PATCH] bes2600: bounce SDIO TX buffers to avoid DMA OOB read + +The SDIO TX path rounds the DMA transfer length up to the host's +current block size and hands that length to dma_map_sg() via +sg_set_buf(&sg[scatters], tx_buffer->buf, align) in sdio_tx_work(). +tx_buffer->buf typically aliases into an skb linear head whose +allocated size matches tx_buffer->len, not the block-aligned +align. The DMA engine (swiotlb / dw_mci IDMAC) therefore reads up +to one block past the end of the skb. On a PineTab2 with KFENCE +enabled this fires as: + + BUG: KFENCE: out-of-bounds read in __pi_memcpy_generic + Out-of-bounds read at ... (704B right of kfence-#...): + __pi_memcpy_generic + swiotlb_tbl_map_single + swiotlb_map + dma_direct_map_sg + __dma_map_sg_attrs + dma_map_sg_attrs + dw_mci_pre_dma_transfer + __dw_mci_start_request + ... + bes_sdio_memcpy_to_io_helper+0x18c/0x288 [bes2600] + sdio_tx_work+0x2b4/0x4a0 [bes2600] + +allocated by ... pskb_expand_head / validate_xmit_skb / tcp_* + +In addition to being undefined behavior, the padding bytes (which +come from whatever memory follows the skb) are transmitted to the +peer, leaking kernel memory on the air. + +Allocate a driver-owned DMA-page bounce buffer sized to +MAX_SDIO_TRANSFER_LEN and use it as the scatter-gather backing for +sdio_tx_work. Each TX buffer is copied into its bounce slot and the +tail (align - tx_buffer->len bytes) is zeroed. This mirrors the +existing bounce pattern already used by bes2600_sdio_memcpy_toio() +via single_gathered_buffer; a separate allocation is used for the +TX path because single_gathered_buffer is only serialised via +sdio_claim_host and sdio_tx_work accumulates scatter entries before +claiming the bus. + +Signed-off-by: Markus Fritsche +--- + bes2600/bes2600_sdio.c | 39 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c +index b943882..e306748 100644 +--- a/drivers/staging/bes2600/bes2600_sdio.c ++++ b/drivers/staging/bes2600/bes2600_sdio.c +@@ -99,6 +99,7 @@ struct sbus_priv { + struct work_struct tx_work; + struct scatterlist tx_sg[BES_SDIO_TX_MULTIPLE_NUM + 1]; + struct scatterlist tx_sg_nosignal[BES_SDIO_TX_MULTIPLE_NUM_NOSIGNAL + 1]; ++ u8 *tx_bounce; + u32 tx_data_cnt; + u32 tx_xfer_cnt; + u32 tx_proc_cnt; +@@ -1151,7 +1152,26 @@ static void sdio_tx_work(struct work_struct *work) + } + } + +- sg_set_buf(&sg[scatters], tx_buffer->buf, align); ++ /* ++ * The transfer length is rounded up to the SDIO block ++ * size, but tx_buffer->buf is only tx_buffer->len bytes ++ * long (it usually aliases into an skb linear head). ++ * Copy into a driver-owned bounce buffer and zero-pad ++ * to the aligned size; otherwise DMA reads past the ++ * skb and leaks adjacent kernel memory on the wire -- ++ * observed as KFENCE OOB reads from ++ * bes_sdio_memcpy_to_io_helper via dma_map_sg. ++ */ ++ if (WARN_ON_ONCE(total_len + align > MAX_SDIO_TRANSFER_LEN)) ++ goto flush_previous; ++ memcpy(self->tx_bounce + total_len, ++ tx_buffer->buf, tx_buffer->len); ++ if (align > tx_buffer->len) ++ memset(self->tx_bounce + total_len + ++ tx_buffer->len, 0, ++ align - tx_buffer->len); ++ sg_set_buf(&sg[scatters], ++ self->tx_bounce + total_len, align); + total_len += align; + ++scatters; + /*del_node:*/ +@@ -1936,6 +1956,17 @@ static int bes2600_sdio_probe(struct sdio_func *func, + if (!self->single_gathered_buffer) + return -ENOMEM; + #endif ++#ifdef BES_SDIO_TX_MULTIPLE_ENABLE ++ self->tx_bounce = (u8 *)__get_dma_pages(GFP_KERNEL, ++ get_order(MAX_SDIO_TRANSFER_LEN)); ++ if (!self->tx_bounce) { ++#ifndef SDIO_HOST_ADMA_SUPPORT ++ free_pages((unsigned long)self->single_gathered_buffer, ++ get_order(MAX_SDIO_TRANSFER_LEN)); ++#endif ++ return -ENOMEM; ++ } ++#endif + #ifdef BES_SDIO_RXTX_TOGGLE + self->fw_started = false; + #endif +@@ -2063,6 +2094,12 @@ static void bes2600_sdio_remove(struct sdio_func *func) + if (self->single_gathered_buffer) { + free_pages((unsigned long)self->single_gathered_buffer, get_order(MAX_SDIO_TRANSFER_LEN)); + } ++#endif ++#ifdef BES_SDIO_TX_MULTIPLE_ENABLE ++ if (self->tx_bounce) { ++ free_pages((unsigned long)self->tx_bounce, ++ get_order(MAX_SDIO_TRANSFER_LEN)); ++ } + #endif + kfree(self); + } +-- +2.54.0 + diff --git a/danctnix-besser-pkgbuild/kernel/PKGBUILD b/danctnix-besser-pkgbuild/kernel/PKGBUILD index 7434cc8bb..f157edb27 100644 --- a/danctnix-besser-pkgbuild/kernel/PKGBUILD +++ b/danctnix-besser-pkgbuild/kernel/PKGBUILD @@ -11,7 +11,7 @@ pkgbase=linux-pinetab2-danctnix-besser pkgver=7.0.danctnix1 -pkgrel=4 +pkgrel=5 pkgdesc='PineTab2 (BESser bes2600 driver patchset)' _srcname=linux-pinetab2 _srctag=v${pkgver%.*}-${pkgver##*.} @@ -58,6 +58,7 @@ source=( 0018-bes2600-Patch-H-bh.c-hygiene-cleanup-drop-fossil-blo.patch 0019-bes2600-take-pending_record_lock-with-_bh-to-fix-SOF.patch 0020-bes2600-export-bus_reset-helpers-for-danctnix-bes260.patch + 0021-bes2600-bounce-sdio-tx-buffers.patch 0002-bes2600-filter-5ghz-scan.patch config # the main kernel config file ) @@ -90,6 +91,7 @@ b2sums=('3d9795083c8938f80f480de0d10bfd9c525640e59d5c7f22983de3f12ee42c84c31be90 'e318299e4cb828220ac7d5142dc41969f22f83f1f791bd46f7f4ce19dbd1d7074b0faa9ac6a4daac4f70e6c7852b38a6482de62111bb7e653cd870d2968fce70' '5c71b88f2ae8a7ebd0932db9a4da72a3ba8c636f31a1bed953a81359588bcb0309f62aa9dee98db62bdc988a9b669341910da2b133d9fb92d14c27d64b54efe9' 'e09273ddcdc44f4d40fe8a69e0fd70b963681ec4434ce63cf6114ea38954891e709ced877e0be914054854e2d295a2991e8c3d8dc0deb244bfc8b0568c681687' + '3be2f7d74baf721ad933f04dea39d79e87a2a1dac3e987615d976e984b1043b90d8ede5ab01c4eb371784eb6ca21cdf69ff7b7c8ee6c678c0aea4bf464fdb92f' '396acbdcf570eada62533c0b8f505ed18077e8432249bab5b8ac8d1107cabc9489bdb91a5780446237ec4fd9ba5fc57a49dff34c16ddab60dc30513fc535f00f' '656a998ab40cb85ee4c00f087b071a91632a6c091da2c84b0f74236b51d2dea6e9db6886625f80ad81dc249d8494ec47cd79d6dd9ea4f5e44f3cde857f861e10')