Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7888c57

Browse files
committed
net: vertexcom: mse102x: Fix possible double free of TX skb
The scope of the TX skb is wider than mse102x_tx_frame_spi, so in case the TX skb needs to be expanded, also its pointer needs to be adjusted. Otherwise the already freed skb pointer would be freed in mse102x_tx_work, which leads to crashes like this: Internal error: Oops: 0000000096000004 [#2] PREEMPT SMP CPU: 0 PID: 712 Comm: kworker/0:1 Tainted: G D 6.6.23 Hardware name: chargebyte Charge SOM DC-ONE (DT) Workqueue: events mse102x_tx_work [mse102x] pstate: 20400009 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : skb_release_data+0xb8/0x1d8 lr : skb_release_data+0x1ac/0x1d8 sp : ffff8000819a3cc0 x29: ffff8000819a3cc0 x28: ffff0000046daa60 x27: ffff0000057f2dc0 x26: ffff000005386c00 x25: 0000000000000002 x24: 00000000ffffffff x23: 0000000000000000 x22: 0000000000000001 x21: ffff0000057f2e50 x20: 0000000000000006 x19: 0000000000000000 x18: ffff00003fdacfcc x17: e69ad452d0c49def x16: 84a005feff870102 x15: 0000000000000000 x14: 000000000000024a x13: 0000000000000002 x12: 0000000000000000 x11: 0000000000000400 x10: 0000000000000930 x9 : ffff00003fd913e8 x8 : fffffc00001bc008 x7 : 0000000000000000 x6 : 0000000000000008 x5 : ffff00003fd91340 x4 : 0000000000000000 x3 : 0000000000000009 x2 : 00000000fffffffe x1 : 0000000000000000 x0 : 0000000000000000 Call trace: skb_release_data+0xb8/0x1d8 kfree_skb_reason+0x48/0xb0 mse102x_tx_work+0x164/0x35c [mse102x] process_one_work+0x138/0x260 worker_thread+0x32c/0x438 kthread+0x118/0x11c ret_from_fork+0x10/0x20 Code: aa1303e0 97fffab6 72001c1f 54000141 (f9400660) Fixes: 2f207cb ("net: vertexcom: Add MSE102x SPI support") Signed-off-by: Stefan Wahren <[email protected]>
1 parent 8b1f8b5 commit 7888c57

File tree

1 file changed

+17
-17
lines changed

1 file changed

+17
-17
lines changed

drivers/net/ethernet/vertexcom/mse102x.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ static inline void mse102x_put_footer(struct sk_buff *skb)
216216
*footer = cpu_to_be16(DET_DFT);
217217
}
218218

219-
static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp,
219+
static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff **txp,
220220
unsigned int pad)
221221
{
222222
struct mse102x_net_spi *mses = to_mse102x_spi(mse);
@@ -226,29 +226,29 @@ static int mse102x_tx_frame_spi(struct mse102x_net *mse, struct sk_buff *txp,
226226
int ret;
227227

228228
netif_dbg(mse, tx_queued, mse->ndev, "%s: skb %p, %d@%p\n",
229-
__func__, txp, txp->len, txp->data);
229+
__func__, *txp, (*txp)->len, (*txp)->data);
230230

231-
if ((skb_headroom(txp) < DET_SOF_LEN) ||
232-
(skb_tailroom(txp) < DET_DFT_LEN + pad)) {
233-
tskb = skb_copy_expand(txp, DET_SOF_LEN, DET_DFT_LEN + pad,
231+
if ((skb_headroom(*txp) < DET_SOF_LEN) ||
232+
(skb_tailroom(*txp) < DET_DFT_LEN + pad)) {
233+
tskb = skb_copy_expand(*txp, DET_SOF_LEN, DET_DFT_LEN + pad,
234234
GFP_KERNEL);
235235
if (!tskb)
236236
return -ENOMEM;
237237

238-
dev_kfree_skb(txp);
239-
txp = tskb;
238+
dev_kfree_skb(*txp);
239+
*txp = tskb;
240240
}
241241

242-
mse102x_push_header(txp);
242+
mse102x_push_header(*txp);
243243

244244
if (pad)
245-
skb_put_zero(txp, pad);
245+
skb_put_zero(*txp, pad);
246246

247-
mse102x_put_footer(txp);
247+
mse102x_put_footer(*txp);
248248

249-
xfer->tx_buf = txp->data;
249+
xfer->tx_buf = (*txp)->data;
250250
xfer->rx_buf = NULL;
251-
xfer->len = txp->len;
251+
xfer->len = (*txp)->len;
252252

253253
ret = spi_sync(mses->spidev, msg);
254254
if (ret < 0) {
@@ -368,7 +368,7 @@ static void mse102x_rx_pkt_spi(struct mse102x_net *mse)
368368
mse->ndev->stats.rx_bytes += rxlen;
369369
}
370370

371-
static int mse102x_tx_pkt_spi(struct mse102x_net *mse, struct sk_buff *txb,
371+
static int mse102x_tx_pkt_spi(struct mse102x_net *mse, struct sk_buff **txb,
372372
unsigned long work_timeout)
373373
{
374374
unsigned int pad = 0;
@@ -377,11 +377,11 @@ static int mse102x_tx_pkt_spi(struct mse102x_net *mse, struct sk_buff *txb,
377377
int ret;
378378
bool first = true;
379379

380-
if (txb->len < ETH_ZLEN)
381-
pad = ETH_ZLEN - txb->len;
380+
if ((*txb)->len < ETH_ZLEN)
381+
pad = ETH_ZLEN - (*txb)->len;
382382

383383
while (1) {
384-
mse102x_tx_cmd_spi(mse, CMD_RTS | (txb->len + pad));
384+
mse102x_tx_cmd_spi(mse, CMD_RTS | ((*txb)->len + pad));
385385
ret = mse102x_rx_cmd_spi(mse, (u8 *)&rx);
386386
cmd_resp = be16_to_cpu(rx);
387387

@@ -437,7 +437,7 @@ static void mse102x_tx_work(struct work_struct *work)
437437

438438
while ((txb = skb_dequeue(&mse->txq))) {
439439
mutex_lock(&mses->lock);
440-
ret = mse102x_tx_pkt_spi(mse, txb, work_timeout);
440+
ret = mse102x_tx_pkt_spi(mse, &txb, work_timeout);
441441
mutex_unlock(&mses->lock);
442442
if (ret) {
443443
mse->ndev->stats.tx_dropped++;

0 commit comments

Comments
 (0)