From: Greg Kroah-Hartman Date: Tue, 16 Jun 2026 07:30:53 +0000 (+0530) Subject: 5.10-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b0c64a4c9b0ad72f08a181ce75a57cdfa9a2bead;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: bluetooth-l2cap-use-chan-timer-to-close-channels-in-cleanup_listen.patch iio-adc-npcm-fix-unbalanced-clk_disable_unprepare.patch iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch iio-dac-ad5686-acquire-lock-when-doing-powerdown-control.patch iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch net-skbuff-fix-missing-zerocopy-reference-in-pskb_carve-helpers.patch serial-samsung_tty-use-port-lock-wrappers.patch tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch tty-serial-samsung-use-u32-for-register-interactions.patch usb-cdns3-gadget-fix-request-skipping-after-clearing-halt.patch usb-gadget-f_hid-fix-device-reference-leak-in-hidg_alloc.patch usb-gadget-f_hid-tidy-error-handling-in-hidg_alloc.patch xfrm-input-hold-netns-during-deferred-transport-reinjection.patch --- diff --git a/queue-5.10/bluetooth-l2cap-use-chan-timer-to-close-channels-in-cleanup_listen.patch b/queue-5.10/bluetooth-l2cap-use-chan-timer-to-close-channels-in-cleanup_listen.patch new file mode 100644 index 0000000000..ae49b5dc03 --- /dev/null +++ b/queue-5.10/bluetooth-l2cap-use-chan-timer-to-close-channels-in-cleanup_listen.patch @@ -0,0 +1,73 @@ +From stable+bounces-260499-greg=kroah.com@vger.kernel.org Thu Jun 4 19:34:49 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 09:45:38 -0400 +Subject: Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen() +To: stable@vger.kernel.org +Cc: Siwei Zhang , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260604134538.3463737-2-sashal@kernel.org> + +From: Siwei Zhang + +[ Upstream commit 8c8e620467a7b51562dbcefbd1f09f288d7d710d ] + +l2cap_chan_close() removes the channel from conn->chan_l, which +must be done under conn->lock. cleanup_listen() runs under the +parent sk_lock, so acquiring conn->lock would invert the +established conn->lock -> chan->lock -> sk_lock order. + +Instead of calling l2cap_chan_close() directly, schedule +l2cap_chan_timeout with delay 0 to close the channel +asynchronously. The timeout handler already acquires conn->lock +and chan->lock in the correct order. + +The timer is only armed when chan->conn is still set: if it is +already NULL, l2cap_conn_del() has already processed this channel +(l2cap_chan_del + l2cap_sock_teardown_cb + l2cap_sock_close_cb), +so there is nothing left to do. If l2cap_conn_del() races in +after the timer is armed, __clear_chan_timer() inside +l2cap_chan_del() cancels it; if the timer has already fired, the +handler returns harmlessly because chan->conn was cleared. + +Fixes: 3df91ea20e74 ("Bluetooth: Revert to mutexes from RCU list") +Cc: # 0b58004: Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() +Signed-off-by: Siwei Zhang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/bluetooth/l2cap_sock.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -1437,6 +1437,10 @@ static void l2cap_sock_cleanup_listen(st + * pin it (hold_unless_zero() additionally skips a chan already past + * its last reference). We then drop the sk lock before taking + * chan->lock, so sk and chan locks are never held together. ++ * ++ * Since we cannot call l2cap_chan_close() without conn->lock, ++ * schedule l2cap_chan_timeout to close the channel; it already ++ * acquires conn->lock -> chan->lock in the correct order. + */ + while ((sk = bt_accept_dequeue(parent, NULL))) { + struct l2cap_chan *chan; +@@ -1454,14 +1458,12 @@ static void l2cap_sock_cleanup_listen(st + state_to_string(chan->state)); + + l2cap_chan_lock(chan); +- __clear_chan_timer(chan); +- l2cap_chan_close(chan, ECONNRESET); +- /* l2cap_conn_del() may already have killed this socket +- * (it sets SOCK_DEAD); skip the duplicate to avoid a +- * double sock_put()/l2cap_chan_put(). ++ /* Since we cannot call l2cap_chan_close() without ++ * conn->lock, schedule its timer to trigger the close ++ * and cleanup of this channel. + */ +- if (!sock_flag(sk, SOCK_DEAD)) +- l2cap_sock_kill(sk); ++ if (chan->conn) ++ __set_chan_timer(chan, 0); + l2cap_chan_unlock(chan); + + l2cap_chan_put(chan); diff --git a/queue-5.10/iio-adc-npcm-fix-unbalanced-clk_disable_unprepare.patch b/queue-5.10/iio-adc-npcm-fix-unbalanced-clk_disable_unprepare.patch new file mode 100644 index 0000000000..980aa36713 --- /dev/null +++ b/queue-5.10/iio-adc-npcm-fix-unbalanced-clk_disable_unprepare.patch @@ -0,0 +1,120 @@ +From stable+bounces-260546-greg=kroah.com@vger.kernel.org Thu Jun 4 22:52:12 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 13:11:57 -0400 +Subject: iio: adc: npcm: fix unbalanced clk_disable_unprepare() +To: stable@vger.kernel.org +Cc: David Carlier , Andy Shevchenko , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260604171157.4039872-1-sashal@kernel.org> + +From: David Carlier + +[ Upstream commit 0d42e2c0bd6ceb89e44c6e065f9bdf9b1df3ef0c ] + +The driver acquired the ADC clock with devm_clk_get() and read its +rate, but never called clk_prepare_enable(). The probe error path and +npcm_adc_remove() both called clk_disable_unprepare() unconditionally, +causing the clk framework's enable/prepare counts to underflow on +probe failure or module unbind. + +The issue went unnoticed because NPCM BMC firmware leaves the ADC +clock enabled at boot, so the driver happened to work in practice. + +Switch to devm_clk_get_enabled() so the clock is properly enabled +during probe and automatically released by the device-managed +cleanup, and drop the now-redundant clk_disable_unprepare() from +both the probe error path and remove(). + +While at it, drop the duplicate error message on devm_request_irq() +failure since the IRQ core already logs it. + +Fixes: 9bf85fbc9d8f ("iio: adc: add NPCM ADC driver") +Signed-off-by: David Carlier +Reviewed-by: Andy Shevchenko +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/adc/npcm_adc.c | 26 ++++++++------------------ + 1 file changed, 8 insertions(+), 18 deletions(-) + +--- a/drivers/iio/adc/npcm_adc.c ++++ b/drivers/iio/adc/npcm_adc.c +@@ -180,7 +180,6 @@ static int npcm_adc_probe(struct platfor + u32 reg_con; + struct npcm_adc *info; + struct iio_dev *indio_dev; +- struct device *dev = &pdev->dev; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); + if (!indio_dev) +@@ -197,7 +196,7 @@ static int npcm_adc_probe(struct platfor + if (IS_ERR(info->reset)) + return PTR_ERR(info->reset); + +- info->adc_clk = devm_clk_get(&pdev->dev, NULL); ++ info->adc_clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(info->adc_clk)) { + dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n"); + return PTR_ERR(info->adc_clk); +@@ -210,17 +209,13 @@ static int npcm_adc_probe(struct platfor + info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2); + + irq = platform_get_irq(pdev, 0); +- if (irq <= 0) { +- ret = -EINVAL; +- goto err_disable_clk; +- } ++ if (irq <= 0) ++ return -EINVAL; + + ret = devm_request_irq(&pdev->dev, irq, npcm_adc_isr, 0, + "NPCM_ADC", indio_dev); +- if (ret < 0) { +- dev_err(dev, "failed requesting interrupt\n"); +- goto err_disable_clk; +- } ++ if (ret < 0) ++ return ret; + + reg_con = ioread32(info->regs + NPCM_ADCCON); + info->vref = devm_regulator_get_optional(&pdev->dev, "vref"); +@@ -228,7 +223,7 @@ static int npcm_adc_probe(struct platfor + ret = regulator_enable(info->vref); + if (ret) { + dev_err(&pdev->dev, "Can't enable ADC reference voltage\n"); +- goto err_disable_clk; ++ return ret; + } + + iowrite32(reg_con & ~NPCM_ADCCON_REFSEL, +@@ -238,10 +233,8 @@ static int npcm_adc_probe(struct platfor + * Any error which is not ENODEV indicates the regulator + * has been specified and so is a failure case. + */ +- if (PTR_ERR(info->vref) != -ENODEV) { +- ret = PTR_ERR(info->vref); +- goto err_disable_clk; +- } ++ if (PTR_ERR(info->vref) != -ENODEV) ++ return PTR_ERR(info->vref); + + /* Use internal reference */ + iowrite32(reg_con | NPCM_ADCCON_REFSEL, +@@ -280,8 +273,6 @@ err_iio_register: + iowrite32(reg_con & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON); + if (!IS_ERR(info->vref)) + regulator_disable(info->vref); +-err_disable_clk: +- clk_disable_unprepare(info->adc_clk); + + return ret; + } +@@ -298,7 +289,6 @@ static int npcm_adc_remove(struct platfo + iowrite32(regtemp & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON); + if (!IS_ERR(info->vref)) + regulator_disable(info->vref); +- clk_disable_unprepare(info->adc_clk); + + return 0; + } diff --git a/queue-5.10/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch b/queue-5.10/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch new file mode 100644 index 0000000000..3025e880f5 --- /dev/null +++ b/queue-5.10/iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch @@ -0,0 +1,38 @@ +From stable+bounces-260587-greg=kroah.com@vger.kernel.org Fri Jun 5 05:19:07 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 19:49:00 -0400 +Subject: iio: chemical: scd30: fix division by zero in write_raw +To: stable@vger.kernel.org +Cc: Antoniu Miclaus , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260604234900.2467781-2-sashal@kernel.org> + +From: Antoniu Miclaus + +[ Upstream commit 5aba4f94b225617a55fed442a70329b2ee19c0a5 ] + +Add a zero check for val2 before using it as a divisor when setting the +sampling frequency. A user writing a zero fractional part to the +sampling_frequency sysfs attribute triggers a division by zero in the +kernel. + +Fixes: 64b3d8b1b0f5 ("iio: chemical: scd30: add core driver") +Signed-off-by: Antoniu Miclaus +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/chemical/scd30_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/chemical/scd30_core.c ++++ b/drivers/iio/chemical/scd30_core.c +@@ -257,7 +257,7 @@ static int scd30_write_raw(struct iio_de + guard(mutex)(&state->lock); + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: +- if (val) ++ if (val || !val2) + return -EINVAL; + + val = 1000000000 / val2; diff --git a/queue-5.10/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch b/queue-5.10/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch new file mode 100644 index 0000000000..399b4205e4 --- /dev/null +++ b/queue-5.10/iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch @@ -0,0 +1,178 @@ +From stable+bounces-260586-greg=kroah.com@vger.kernel.org Fri Jun 5 05:20:48 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 19:48:59 -0400 +Subject: iio: chemical: scd30: Use guard(mutex) to allow early returns +To: stable@vger.kernel.org +Cc: Jonathan Cameron , David Lechner , Tomasz Duszynski , Sasha Levin +Message-ID: <20260604234900.2467781-1-sashal@kernel.org> + +From: Jonathan Cameron + +[ Upstream commit 5feb5532870fbced5d6f450b8061a33f461b88ca ] + +Auto cleanup based release of the lock allows for simpler code flow in a +few functions with large multiplexing style switch statements and no +common operations following the switch. + +Suggested-by: David Lechner +Cc: Tomasz Duszynski +Reviewed-by: David Lechner +Link: https://patch.msgid.link/20250209180624.701140-3-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Stable-dep-of: 5aba4f94b225 ("iio: chemical: scd30: fix division by zero in write_raw") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/chemical/scd30_core.c | 63 ++++++++++++++++---------------------- + 1 file changed, 28 insertions(+), 35 deletions(-) + +--- a/drivers/iio/chemical/scd30_core.c ++++ b/drivers/iio/chemical/scd30_core.c +@@ -5,6 +5,7 @@ + * Copyright (c) 2020 Tomasz Duszynski + */ + #include ++#include + #include + #include + #include +@@ -198,112 +199,104 @@ static int scd30_read_raw(struct iio_dev + int *val, int *val2, long mask) + { + struct scd30_state *state = iio_priv(indio_dev); +- int ret = -EINVAL; ++ int ret; + u16 tmp; + +- mutex_lock(&state->lock); ++ guard(mutex)(&state->lock); + switch (mask) { + case IIO_CHAN_INFO_RAW: + case IIO_CHAN_INFO_PROCESSED: + if (chan->output) { + *val = state->pressure_comp; +- ret = IIO_VAL_INT; +- break; ++ return IIO_VAL_INT; + } + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) +- break; ++ return ret; + + ret = scd30_read(state); + if (ret) { + iio_device_release_direct_mode(indio_dev); +- break; ++ return ret; + } + + *val = state->meas[chan->address]; + iio_device_release_direct_mode(indio_dev); +- ret = IIO_VAL_INT; +- break; ++ return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 1; +- ret = IIO_VAL_INT_PLUS_MICRO; +- break; ++ return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = scd30_command_read(state, CMD_MEAS_INTERVAL, &tmp); + if (ret) +- break; ++ return ret; + + *val = 0; + *val2 = 1000000000 / tmp; +- ret = IIO_VAL_INT_PLUS_NANO; +- break; ++ return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_CALIBBIAS: + ret = scd30_command_read(state, CMD_TEMP_OFFSET, &tmp); + if (ret) +- break; ++ return ret; + + *val = tmp; +- ret = IIO_VAL_INT; +- break; ++ return IIO_VAL_INT; ++ default: ++ return -EINVAL; + } +- mutex_unlock(&state->lock); +- +- return ret; + } + + static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, + int val, int val2, long mask) + { + struct scd30_state *state = iio_priv(indio_dev); +- int ret = -EINVAL; ++ int ret; + +- mutex_lock(&state->lock); ++ guard(mutex)(&state->lock); + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val) +- break; ++ return -EINVAL; + + val = 1000000000 / val2; + if (val < SCD30_MEAS_INTERVAL_MIN_S || val > SCD30_MEAS_INTERVAL_MAX_S) +- break; ++ return -EINVAL; + + ret = scd30_command_write(state, CMD_MEAS_INTERVAL, val); + if (ret) +- break; ++ return ret; + + state->meas_interval = val; +- break; ++ return 0; + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_PRESSURE: + if (val < SCD30_PRESSURE_COMP_MIN_MBAR || + val > SCD30_PRESSURE_COMP_MAX_MBAR) +- break; ++ return -EINVAL; + + ret = scd30_command_write(state, CMD_START_MEAS, val); + if (ret) +- break; ++ return ret; + + state->pressure_comp = val; +- break; ++ return 0; + default: +- break; ++ return -EINVAL; + } +- break; + case IIO_CHAN_INFO_CALIBBIAS: + if (val < 0 || val > SCD30_TEMP_OFFSET_MAX) +- break; ++ return -EINVAL; + /* + * Manufacturer does not explicitly specify min/max sensible + * values hence check is omitted for simplicity. + */ +- ret = scd30_command_write(state, CMD_TEMP_OFFSET / 10, val); ++ return scd30_command_write(state, CMD_TEMP_OFFSET / 10, val); ++ default: ++ return -EINVAL; + } +- mutex_unlock(&state->lock); +- +- return ret; + } + + static int scd30_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, diff --git a/queue-5.10/iio-dac-ad5686-acquire-lock-when-doing-powerdown-control.patch b/queue-5.10/iio-dac-ad5686-acquire-lock-when-doing-powerdown-control.patch new file mode 100644 index 0000000000..6efeeb983c --- /dev/null +++ b/queue-5.10/iio-dac-ad5686-acquire-lock-when-doing-powerdown-control.patch @@ -0,0 +1,69 @@ +From stable+bounces-260533-greg=kroah.com@vger.kernel.org Thu Jun 4 21:26:20 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 11:49:19 -0400 +Subject: iio: dac: ad5686: acquire lock when doing powerdown control +To: stable@vger.kernel.org +Cc: Rodrigo Alencar , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260604154919.3732423-1-sashal@kernel.org> + +From: Rodrigo Alencar + +[ Upstream commit 5237c3175cae5ab05f18878cec3301a04403859e ] + +Protect access of pwr_down_mode and pwr_down_mask fields with existing +mutex lock. Each channel exposes their own attributes for controlling +powerdown modes and powerdown state. This fixes potential race conditions +as those the write functions perform non-atomic read-modify-write +operations to those pwr_down_* fields. This issue exists since the ad5686 +driver was first introduced. + +Fixes: c2f37c8dcadc ("iio: dac: New driver for AD5686R, AD5685R, AD5684R Digital to analog converters") +Signed-off-by: Rodrigo Alencar +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/dac/ad5686.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/iio/dac/ad5686.c ++++ b/drivers/iio/dac/ad5686.c +@@ -30,6 +30,8 @@ static int ad5686_get_powerdown_mode(str + { + struct ad5686_state *st = iio_priv(indio_dev); + ++ guard(mutex)(&st->lock); ++ + return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1; + } + +@@ -39,6 +41,8 @@ static int ad5686_set_powerdown_mode(str + { + struct ad5686_state *st = iio_priv(indio_dev); + ++ guard(mutex)(&st->lock); ++ + st->pwr_down_mode &= ~(0x3 << (chan->channel * 2)); + st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2)); + +@@ -57,7 +61,9 @@ static ssize_t ad5686_read_dac_powerdown + { + struct ad5686_state *st = iio_priv(indio_dev); + +- return sprintf(buf, "%d\n", !!(st->pwr_down_mask & ++ guard(mutex)(&st->lock); ++ ++ return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask & + (0x3 << (chan->channel * 2)))); + } + +@@ -77,6 +83,8 @@ static ssize_t ad5686_write_dac_powerdow + if (ret) + return ret; + ++ guard(mutex)(&st->lock); ++ + if (readin) + st->pwr_down_mask |= (0x3 << (chan->channel * 2)); + else diff --git a/queue-5.10/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch b/queue-5.10/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch new file mode 100644 index 0000000000..d34c4b990b --- /dev/null +++ b/queue-5.10/iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch @@ -0,0 +1,65 @@ +From stable+bounces-260609-greg=kroah.com@vger.kernel.org Fri Jun 5 07:22:06 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 21:51:51 -0400 +Subject: iio: dac: ad5686: fix ref bit initialization for single-channel parts +To: stable@vger.kernel.org +Cc: Rodrigo Alencar , Andy Shevchenko , Stable@vger.kernel.org, Jonathan Cameron , Sasha Levin +Message-ID: <20260605015151.3131582-1-sashal@kernel.org> + +From: Rodrigo Alencar + +[ Upstream commit ecae2ae606d493cf11457946436335bd0e726663 ] + +The reference bit position was ignored when writing the register at the +probe() function (!!val was used). When such bit is 1, internal voltage +reference is disabled so that an external one can be used. For +multi-channel devices, bit 0 of the Internal Reference Setup command +behaves the same way, so AD5686_REF_BIT_MSK is created. The issue exists +since support for single-channel devices were first introduced. + +Fixes: be1b24d24541 ("iio:dac:ad5686: Add AD5691R/AD5692R/AD5693/AD5693R support") +Reviewed-by: Andy Shevchenko +Signed-off-by: Rodrigo Alencar +Cc: +Signed-off-by: Jonathan Cameron +[ adapted `has_external_vref` to the in-tree equivalent `voltage_uv` variable in the `val =` computation ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/dac/ad5686.c | 6 +++--- + drivers/iio/dac/ad5686.h | 1 + + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/iio/dac/ad5686.c ++++ b/drivers/iio/dac/ad5686.c +@@ -496,7 +496,7 @@ int ad5686_probe(struct device *dev, + break; + case AD5686_REGMAP: + cmd = AD5686_CMD_INTERNAL_REFER_SETUP; +- ref_bit_msk = 0; ++ ref_bit_msk = AD5686_REF_BIT_MSK; + break; + case AD5693_REGMAP: + cmd = AD5686_CMD_CONTROL_REG; +@@ -508,9 +508,9 @@ int ad5686_probe(struct device *dev, + goto error_disable_reg; + } + +- val = (voltage_uv | ref_bit_msk); ++ val = voltage_uv ? ref_bit_msk : 0; + +- ret = st->write(st, cmd, 0, !!val); ++ ret = st->write(st, cmd, 0, val); + if (ret) + goto error_disable_reg; + +--- a/drivers/iio/dac/ad5686.h ++++ b/drivers/iio/dac/ad5686.h +@@ -44,6 +44,7 @@ + + #define AD5310_REF_BIT_MSK BIT(8) + #define AD5683_REF_BIT_MSK BIT(12) ++#define AD5686_REF_BIT_MSK BIT(0) + #define AD5693_REF_BIT_MSK BIT(12) + + /** diff --git a/queue-5.10/iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch b/queue-5.10/iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch new file mode 100644 index 0000000000..8a72d99747 --- /dev/null +++ b/queue-5.10/iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch @@ -0,0 +1,39 @@ +From stable+bounces-260590-greg=kroah.com@vger.kernel.org Fri Jun 5 05:19:45 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 19:49:37 -0400 +Subject: iio: gyro: adis16260: fix division by zero in write_raw +To: stable@vger.kernel.org +Cc: "Antoniu Miclaus" , "Nuno Sá" , Stable@vger.kernel.org, "Jonathan Cameron" , "Sasha Levin" +Message-ID: <20260604234937.2471947-1-sashal@kernel.org> + +From: Antoniu Miclaus + +[ Upstream commit 761e8b489e6cf166c574034b70637f8a7eadd0ee ] + +Add a validation check for the sampling frequency value before using it +as a divisor. A user writing zero to the sampling_frequency sysfs +attribute triggers a division by zero in the kernel. + +Fixes: 089a41985c6c ("staging: iio: adis16260 digital gyro driver") +Signed-off-by: Antoniu Miclaus +Reviewed-by: Nuno Sá +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/gyro/adis16260.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/iio/gyro/adis16260.c ++++ b/drivers/iio/gyro/adis16260.c +@@ -293,6 +293,9 @@ static int adis16260_write_raw(struct ii + addr = adis16260_addresses[chan->scan_index][1]; + return adis_write_reg_16(adis, addr, val); + case IIO_CHAN_INFO_SAMP_FREQ: ++ if (val <= 0) ++ return -EINVAL; ++ + mutex_lock(&adis->state_lock); + if (spi_get_device_id(adis->spi)->driver_data) + t = 256 / val; diff --git a/queue-5.10/net-skbuff-fix-missing-zerocopy-reference-in-pskb_carve-helpers.patch b/queue-5.10/net-skbuff-fix-missing-zerocopy-reference-in-pskb_carve-helpers.patch new file mode 100644 index 0000000000..81a3a1b4e0 --- /dev/null +++ b/queue-5.10/net-skbuff-fix-missing-zerocopy-reference-in-pskb_carve-helpers.patch @@ -0,0 +1,92 @@ +From stable+bounces-260764-greg=kroah.com@vger.kernel.org Sat Jun 6 00:10:11 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 14:31:31 -0400 +Subject: net: skbuff: fix missing zerocopy reference in pskb_carve helpers +To: stable@vger.kernel.org +Cc: Minh Nguyen , Willem de Bruijn , Paolo Abeni , Sasha Levin +Message-ID: <20260605183131.2056525-1-sashal@kernel.org> + +From: Minh Nguyen + +[ Upstream commit 98d0912e9f841e5529a5b89a972805f34cb1c69d ] + +pskb_carve_inside_header() and pskb_carve_inside_nonlinear() both copy +the old skb_shared_info header into a new buffer via memcpy(), which +includes the destructor_arg pointer (uarg) for MSG_ZEROCOPY skbs. +Neither function calls net_zcopy_get() for the new shinfo, creating an +unaccounted holder: every skb_shared_info with destructor_arg set will +call skb_zcopy_clear() once when freed, but the corresponding +net_zcopy_get() was never called for the new copy. Repeated calls +drive uarg->refcnt to zero prematurely, freeing ubuf_info_msgzc while +TX skbs still hold live destructor_arg pointers. + +KASAN reports use-after-free on a freed ubuf_info_msgzc: + + BUG: KASAN: slab-use-after-free in skb_release_data+0x77b/0x810 + Read of size 8 at addr ffff88801574d3e8 by task poc/220 + + Call Trace: + skb_release_data+0x77b/0x810 + kfree_skb_list_reason+0x13e/0x610 + skb_release_data+0x4cd/0x810 + sk_skb_reason_drop+0xf3/0x340 + skb_queue_purge_reason+0x282/0x440 + rds_tcp_inc_free+0x1e/0x30 + rds_recvmsg+0x354/0x1780 + __sys_recvmsg+0xdf/0x180 + + Allocated by task 219: + msg_zerocopy_realloc+0x157/0x7b0 + tcp_sendmsg_locked+0x2892/0x3ba0 + + Freed by task 219: + ip_recv_error+0x74a/0xb10 + tcp_recvmsg+0x475/0x530 + +The skb consuming the late access still referenced the same uarg via +shinfo->destructor_arg copied by pskb_carve_inside_nonlinear() without +a refcount bump. This has been verified to be reliably exploitable: a +working proof-of-concept achieves full root privilege escalation from +an unprivileged local user on a default kernel configuration. + +The fix follows the pattern of pskb_expand_head() which has the same +memcpy/cloned structure. For pskb_carve_inside_header(), net_zcopy_get() +is placed after skb_orphan_frags() succeeds, so the orphan error path +needs no cleanup. For pskb_carve_inside_nonlinear(), net_zcopy_get() is +placed after all failure points and just before skb_release_data(), so +no error path needs cleanup at all -- matching pskb_expand_head() more +closely and avoiding the need for a balancing net_zcopy_put(). + +Fixes: 6fa01ccd8830 ("skbuff: Add pskb_extract() helper function") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-sonnet-4-6 +Signed-off-by: Minh Nguyen +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260526041240.329462-1-minhnguyen.080505@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/core/skbuff.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -6058,6 +6058,8 @@ static int pskb_carve_inside_header(stru + kfree(data); + return -ENOMEM; + } ++ if (skb_zcopy(skb)) ++ refcount_inc(&skb_uarg(skb)->refcnt); + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + skb_frag_ref(skb, i); + if (skb_has_frag_list(skb)) +@@ -6210,6 +6212,8 @@ static int pskb_carve_inside_nonlinear(s + kfree(data); + return -ENOMEM; + } ++ if (skb_zcopy(skb)) ++ refcount_inc(&skb_uarg(skb)->refcnt); + skb_release_data(skb); + + skb->head = data; diff --git a/queue-5.10/serial-samsung_tty-use-port-lock-wrappers.patch b/queue-5.10/serial-samsung_tty-use-port-lock-wrappers.patch new file mode 100644 index 0000000000..164d065978 --- /dev/null +++ b/queue-5.10/serial-samsung_tty-use-port-lock-wrappers.patch @@ -0,0 +1,204 @@ +From sashal@kernel.org Sat Jun 6 01:08:26 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 15:38:21 -0400 +Subject: serial: samsung_tty: Use port lock wrappers +To: stable@vger.kernel.org +Cc: Thomas Gleixner , John Ogness , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605193823.2169333-1-sashal@kernel.org> + +From: Thomas Gleixner + +[ Upstream commit 97d7a9aeba1d424c2359f1686d02c75d798ad184 ] + +When a serial port is used for kernel console output, then all +modifications to the UART registers which are done from other contexts, +e.g. getty, termios, are interference points for the kernel console. + +So far this has been ignored and the printk output is based on the +principle of hope. The rework of the console infrastructure which aims to +support threaded and atomic consoles, requires to mark sections which +modify the UART registers as unsafe. This allows the atomic write function +to make informed decisions and eventually to restore operational state. It +also allows to prevent the regular UART code from modifying UART registers +while printk output is in progress. + +All modifications of UART registers are guarded by the UART port lock, +which provides an obvious synchronization point with the console +infrastructure. + +To avoid adding this functionality to all UART drivers, wrap the +spin_[un]lock*() invocations for uart_port::lock into helper functions +which just contain the spin_[un]lock*() invocations for now. In a +subsequent step these helpers will gain the console synchronization +mechanisms. + +Converted with coccinelle. No functional change. + +Signed-off-by: Thomas Gleixner +Signed-off-by: John Ogness +Link: https://lore.kernel.org/r/20230914183831.587273-54-john.ogness@linutronix.de +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/samsung_tty.c | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +--- a/drivers/tty/serial/samsung_tty.c ++++ b/drivers/tty/serial/samsung_tty.c +@@ -245,7 +245,7 @@ static void s3c24xx_serial_rx_enable(str + unsigned int ucon, ufcon; + int count = 10000; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + while (--count && !s3c24xx_serial_txempty_nofifo(port)) + udelay(100); +@@ -259,7 +259,7 @@ static void s3c24xx_serial_rx_enable(str + wr_regl(port, S3C2410_UCON, ucon); + + ourport->rx_enabled = 1; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void s3c24xx_serial_rx_disable(struct uart_port *port) +@@ -268,14 +268,14 @@ static void s3c24xx_serial_rx_disable(st + unsigned long flags; + unsigned int ucon; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ucon = rd_regl(port, S3C2410_UCON); + ucon &= ~S3C2410_UCON_RXIRQMODE; + wr_regl(port, S3C2410_UCON, ucon); + + ourport->rx_enabled = 0; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void s3c24xx_serial_stop_tx(struct uart_port *port) +@@ -334,7 +334,7 @@ static void s3c24xx_serial_tx_dma_comple + dma_sync_single_for_cpu(ourport->port.dev, dma->tx_transfer_addr, + dma->tx_size, DMA_TO_DEVICE); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1); + port->icount.tx += count; +@@ -344,7 +344,7 @@ static void s3c24xx_serial_tx_dma_comple + uart_write_wakeup(port); + + s3c24xx_serial_start_next_tx(ourport); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void enable_tx_dma(struct s3c24xx_uart_port *ourport) +@@ -579,7 +579,7 @@ static void s3c24xx_serial_rx_dma_comple + received = dma->rx_bytes_requested - state.residue; + async_tx_ack(dma->rx_desc); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (received) + s3c24xx_uart_copy_rx_to_tty(ourport, t, received); +@@ -591,7 +591,7 @@ static void s3c24xx_serial_rx_dma_comple + + s3c64xx_start_rx_dma(ourport); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport) +@@ -679,7 +679,7 @@ static irqreturn_t s3c24xx_serial_rx_cha + utrstat = rd_regl(port, S3C2410_UTRSTAT); + rd_regl(port, S3C2410_UFSTAT); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) { + s3c64xx_start_rx_dma(ourport); +@@ -708,7 +708,7 @@ static irqreturn_t s3c24xx_serial_rx_cha + wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT); + + finish: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -806,9 +806,9 @@ static irqreturn_t s3c24xx_serial_rx_cha + struct uart_port *port = &ourport->port; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + s3c24xx_serial_rx_drain_fifo(ourport); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -956,7 +956,7 @@ static void s3c24xx_serial_break_ctl(str + unsigned long flags; + unsigned int ucon; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ucon = rd_regl(port, S3C2410_UCON); + +@@ -967,7 +967,7 @@ static void s3c24xx_serial_break_ctl(str + + wr_regl(port, S3C2410_UCON, ucon); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) +@@ -1192,7 +1192,7 @@ static int s3c64xx_serial_startup(struct + ourport->tx_enabled = 0; + ourport->tx_claimed = 1; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ufcon = rd_regl(port, S3C2410_UFCON); + ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8; +@@ -1202,7 +1202,7 @@ static int s3c64xx_serial_startup(struct + + enable_rx_pio(ourport); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Enable Rx Interrupt */ + s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM); +@@ -1479,7 +1479,7 @@ static void s3c24xx_serial_set_termios(s + ulcon |= S3C2410_LCON_PNONE; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + dev_dbg(port->dev, + "setting ulcon to %08x, brddiv to %d, udivslot %08x\n", +@@ -1537,7 +1537,7 @@ static void s3c24xx_serial_set_termios(s + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= RXSTAT_DUMMY_READ; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *s3c24xx_serial_type(struct uart_port *port) diff --git a/queue-5.10/series b/queue-5.10/series index 076feaadec..17f9652966 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -314,3 +314,18 @@ mm-huge_memory-update-file-pmd-counter-before-folio_put.patch rdma-umem-fix-kernel-doc-warnings.patch rdma-move-dma-block-iterator-logic-into-dedicated-files.patch rdma-umem-fix-truncation-for-block-sizes-4g.patch +bluetooth-l2cap-use-chan-timer-to-close-channels-in-cleanup_listen.patch +iio-dac-ad5686-acquire-lock-when-doing-powerdown-control.patch +iio-adc-npcm-fix-unbalanced-clk_disable_unprepare.patch +usb-cdns3-gadget-fix-request-skipping-after-clearing-halt.patch +iio-chemical-scd30-use-guard-mutex-to-allow-early-returns.patch +iio-chemical-scd30-fix-division-by-zero-in-write_raw.patch +iio-gyro-adis16260-fix-division-by-zero-in-write_raw.patch +iio-dac-ad5686-fix-ref-bit-initialization-for-single-channel-parts.patch +xfrm-input-hold-netns-during-deferred-transport-reinjection.patch +net-skbuff-fix-missing-zerocopy-reference-in-pskb_carve-helpers.patch +serial-samsung_tty-use-port-lock-wrappers.patch +tty-serial-samsung-use-u32-for-register-interactions.patch +tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch +usb-gadget-f_hid-tidy-error-handling-in-hidg_alloc.patch +usb-gadget-f_hid-fix-device-reference-leak-in-hidg_alloc.patch diff --git a/queue-5.10/tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch b/queue-5.10/tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch new file mode 100644 index 0000000000..c3ee56d975 --- /dev/null +++ b/queue-5.10/tty-serial-samsung-remove-redundant-port-lock-acquisition-in-rx-helpers.patch @@ -0,0 +1,85 @@ +From stable+bounces-260807-greg=kroah.com@vger.kernel.org Sat Jun 6 01:08:30 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 15:38:23 -0400 +Subject: tty: serial: samsung: Remove redundant port lock acquisition in rx helpers +To: stable@vger.kernel.org +Cc: Tudor Ambarus , stable , John Ogness , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605193823.2169333-3-sashal@kernel.org> + +From: Tudor Ambarus + +[ Upstream commit a3bb136bff5e6a5e48cdd813246c9c4686feaaa9 ] + +Sashiko identified a deadlock when the console flow is engaged [1]. + +When console flow control is enabled (UPF_CONS_FLOW), +s3c24xx_serial_stop_tx() calls s3c24xx_serial_rx_enable() and +s3c24xx_serial_start_tx() calls s3c24xx_serial_rx_disable(). + +The serial core framework invokes the .stop_tx() and .start_tx() +callbacks with the port->lock spinlock already held. Furthermore, all +internal driver paths that invoke stop_tx (such as the DMA TX +completion handler s3c24xx_serial_tx_dma_complete() or the PIO TX IRQ +handler s3c24xx_serial_tx_irq()) also acquire port->lock prior to +calling it. (Note that s3c24xx_serial_start_tx() is only invoked by the +serial core). + +However, s3c24xx_serial_rx_enable() and s3c24xx_serial_rx_disable() +unconditionally attempt to acquire port->lock again using +uart_port_lock_irqsave(). Since spinlocks are not recursive, this +causes a deadlock on the same CPU when console flow control is engaged. + +Remove the redundant lock acquisition from both rx helper functions. + +Cc: stable +Fixes: b497549a035c ("[ARM] S3C24XX: Split serial driver into core and per-cpu drivers") +Reported-by: John Ogness +Closes: https://sashiko.dev/#/patchset/20260506121606.5805-1-john.ogness%40linutronix.de [1] +Signed-off-by: Tudor Ambarus +Link: https://patch.msgid.link/20260515-samsung-tty-flow-control-deadlock-v1-1-93255edbc9bc@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/samsung_tty.c | 8 -------- + 1 file changed, 8 deletions(-) + +--- a/drivers/tty/serial/samsung_tty.c ++++ b/drivers/tty/serial/samsung_tty.c +@@ -241,12 +241,9 @@ static int s3c24xx_serial_has_interrupt_ + static void s3c24xx_serial_rx_enable(struct uart_port *port) + { + struct s3c24xx_uart_port *ourport = to_ourport(port); +- unsigned long flags; + int count = 10000; + u32 ucon, ufcon; + +- uart_port_lock_irqsave(port, &flags); +- + while (--count && !s3c24xx_serial_txempty_nofifo(port)) + udelay(100); + +@@ -259,23 +256,18 @@ static void s3c24xx_serial_rx_enable(str + wr_regl(port, S3C2410_UCON, ucon); + + ourport->rx_enabled = 1; +- uart_port_unlock_irqrestore(port, flags); + } + + static void s3c24xx_serial_rx_disable(struct uart_port *port) + { + struct s3c24xx_uart_port *ourport = to_ourport(port); +- unsigned long flags; + u32 ucon; + +- uart_port_lock_irqsave(port, &flags); +- + ucon = rd_regl(port, S3C2410_UCON); + ucon &= ~S3C2410_UCON_RXIRQMODE; + wr_regl(port, S3C2410_UCON, ucon); + + ourport->rx_enabled = 0; +- uart_port_unlock_irqrestore(port, flags); + } + + static void s3c24xx_serial_stop_tx(struct uart_port *port) diff --git a/queue-5.10/tty-serial-samsung-use-u32-for-register-interactions.patch b/queue-5.10/tty-serial-samsung-use-u32-for-register-interactions.patch new file mode 100644 index 0000000000..3e0e312292 --- /dev/null +++ b/queue-5.10/tty-serial-samsung-use-u32-for-register-interactions.patch @@ -0,0 +1,314 @@ +From stable+bounces-260806-greg=kroah.com@vger.kernel.org Sat Jun 6 01:08:30 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 15:38:22 -0400 +Subject: tty: serial: samsung: use u32 for register interactions +To: stable@vger.kernel.org +Cc: Tudor Ambarus , Sam Protsenko , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605193823.2169333-2-sashal@kernel.org> + +From: Tudor Ambarus + +[ Upstream commit 032a725c16add79332d774348d7ad7d0d4b86479 ] + +All registers of the IP have 32 bits. Use u32 variables when reading +or writing from/to the registers. The purpose of those variables becomes +clearer. + +Reviewed-by: Sam Protsenko +Signed-off-by: Tudor Ambarus +Link: https://lore.kernel.org/r/20240119104526.1221243-9-tudor.ambarus@linaro.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/samsung_tty.c | 67 +++++++++++++++++++-------------------- + 1 file changed, 34 insertions(+), 33 deletions(-) + +--- a/drivers/tty/serial/samsung_tty.c ++++ b/drivers/tty/serial/samsung_tty.c +@@ -186,7 +186,7 @@ static void wr_reg(struct uart_port *por + /* Byte-order aware bit setting/clearing functions. */ + + static inline void s3c24xx_set_bit(struct uart_port *port, int idx, +- unsigned int reg) ++ u32 reg) + { + unsigned long flags; + u32 val; +@@ -199,7 +199,7 @@ static inline void s3c24xx_set_bit(struc + } + + static inline void s3c24xx_clear_bit(struct uart_port *port, int idx, +- unsigned int reg) ++ u32 reg) + { + unsigned long flags; + u32 val; +@@ -242,8 +242,8 @@ static void s3c24xx_serial_rx_enable(str + { + struct s3c24xx_uart_port *ourport = to_ourport(port); + unsigned long flags; +- unsigned int ucon, ufcon; + int count = 10000; ++ u32 ucon, ufcon; + + uart_port_lock_irqsave(port, &flags); + +@@ -266,7 +266,7 @@ static void s3c24xx_serial_rx_disable(st + { + struct s3c24xx_uart_port *ourport = to_ourport(port); + unsigned long flags; +- unsigned int ucon; ++ u32 ucon; + + uart_port_lock_irqsave(port, &flags); + +@@ -551,7 +551,7 @@ static inline struct s3c2410_uartcfg + } + + static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, +- unsigned long ufstat) ++ u32 ufstat) + { + struct s3c24xx_uart_info *info = ourport->info; + +@@ -623,7 +623,7 @@ static void s3c64xx_start_rx_dma(struct + static void enable_rx_dma(struct s3c24xx_uart_port *ourport) + { + struct uart_port *port = &ourport->port; +- unsigned int ucon; ++ u32 ucon; + + /* set Rx mode to DMA mode */ + ucon = rd_regl(port, S3C2410_UCON); +@@ -646,7 +646,7 @@ static void enable_rx_dma(struct s3c24xx + static void enable_rx_pio(struct s3c24xx_uart_port *ourport) + { + struct uart_port *port = &ourport->port; +- unsigned int ucon; ++ u32 ucon; + + /* set Rx mode to DMA mode */ + ucon = rd_regl(port, S3C2410_UCON); +@@ -667,7 +667,6 @@ static void s3c24xx_serial_rx_drain_fifo + + static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) + { +- unsigned int utrstat, received; + struct s3c24xx_uart_port *ourport = dev_id; + struct uart_port *port = &ourport->port; + struct s3c24xx_uart_dma *dma = ourport->dma; +@@ -675,6 +674,8 @@ static irqreturn_t s3c24xx_serial_rx_cha + struct tty_port *t = &port->state->port; + unsigned long flags; + struct dma_tx_state state; ++ unsigned int received; ++ u32 utrstat; + + utrstat = rd_regl(port, S3C2410_UTRSTAT); + rd_regl(port, S3C2410_UFSTAT); +@@ -716,9 +717,10 @@ finish: + static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport) + { + struct uart_port *port = &ourport->port; +- unsigned int ufcon, ch, flag, ufstat, uerstat; ++ unsigned int ch, flag; + unsigned int fifocnt = 0; + int max_count = port->fifosize; ++ u32 ufcon, ufstat, uerstat; + + while (max_count-- > 0) { + /* +@@ -898,7 +900,7 @@ static irqreturn_t s3c64xx_serial_handle + { + struct s3c24xx_uart_port *ourport = id; + struct uart_port *port = &ourport->port; +- unsigned int pend = rd_regl(port, S3C64XX_UINTP); ++ u32 pend = rd_regl(port, S3C64XX_UINTP); + irqreturn_t ret = IRQ_HANDLED; + + if (pend & S3C64XX_UINTM_RXD_MSK) { +@@ -915,8 +917,8 @@ static irqreturn_t s3c64xx_serial_handle + static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) + { + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); +- unsigned long ufstat = rd_regl(port, S3C2410_UFSTAT); +- unsigned long ufcon = rd_regl(port, S3C2410_UFCON); ++ u32 ufstat = rd_regl(port, S3C2410_UFSTAT); ++ u32 ufcon = rd_regl(port, S3C2410_UFCON); + + if (ufcon & S3C2410_UFCON_FIFOMODE) { + if ((ufstat & info->tx_fifomask) != 0 || +@@ -931,7 +933,7 @@ static unsigned int s3c24xx_serial_tx_em + /* no modem control lines */ + static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port) + { +- unsigned int umstat = rd_reg(port, S3C2410_UMSTAT); ++ u32 umstat = rd_reg(port, S3C2410_UMSTAT); + + if (umstat & S3C2410_UMSTAT_CTS) + return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; +@@ -941,7 +943,7 @@ static unsigned int s3c24xx_serial_get_m + + static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl) + { +- unsigned int umcon = rd_regl(port, S3C2410_UMCON); ++ u32 umcon = rd_regl(port, S3C2410_UMCON); + + if (mctrl & TIOCM_RTS) + umcon |= S3C2410_UMCOM_RTS_LOW; +@@ -954,7 +956,7 @@ static void s3c24xx_serial_set_mctrl(str + static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) + { + unsigned long flags; +- unsigned int ucon; ++ u32 ucon; + + uart_port_lock_irqsave(port, &flags); + +@@ -1167,7 +1169,7 @@ static int s3c64xx_serial_startup(struct + { + struct s3c24xx_uart_port *ourport = to_ourport(port); + unsigned long flags; +- unsigned int ufcon; ++ u32 ufcon; + int ret; + + wr_regl(port, S3C64XX_UINTM, 0xf); +@@ -1210,6 +1212,7 @@ static int s3c64xx_serial_startup(struct + return ret; + } + ++ + /* power power management control */ + + static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, +@@ -1261,7 +1264,7 @@ static void s3c24xx_serial_pm(struct uar + static inline int s3c24xx_serial_getsource(struct uart_port *port) + { + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); +- unsigned int ucon; ++ u32 ucon; + + if (info->num_clks == 1) + return 0; +@@ -1275,7 +1278,7 @@ static void s3c24xx_serial_setsource(str + unsigned int clk_sel) + { + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); +- unsigned int ucon; ++ u32 ucon; + + if (info->num_clks == 1) + return; +@@ -1394,9 +1397,8 @@ static void s3c24xx_serial_set_termios(s + struct clk *clk = ERR_PTR(-EINVAL); + unsigned long flags; + unsigned int baud, quot, clk_sel = 0; +- unsigned int ulcon; +- unsigned int umcon; + unsigned int udivslot = 0; ++ u32 ulcon, umcon; + + /* + * We don't support modem control lines. +@@ -1712,7 +1714,7 @@ static void s3c24xx_serial_resetport(str + struct s3c2410_uartcfg *cfg) + { + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); +- unsigned long ucon = rd_regl(port, S3C2410_UCON); ++ u32 ucon = rd_regl(port, S3C2410_UCON); + unsigned int ucon_mask; + + ucon_mask = info->clksel_mask; +@@ -2150,7 +2152,7 @@ static int s3c24xx_serial_resume_noirq(s + if (port) { + /* restore IRQ mask */ + if (s3c24xx_serial_has_interrupt_mask(port)) { +- unsigned int uintm = 0xf; ++ u32 uintm = 0xf; + + if (ourport->tx_enabled) + uintm &= ~S3C64XX_UINTM_TXD_MSK; +@@ -2188,10 +2190,10 @@ static const struct dev_pm_ops s3c24xx_s + static struct uart_port *cons_uart; + + static int +-s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) ++s3c24xx_serial_console_txrdy(struct uart_port *port, u32 ufcon) + { + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); +- unsigned long ufstat, utrstat; ++ u32 ufstat, utrstat; + + if (ufcon & S3C2410_UFCON_FIFOMODE) { + /* fifo mode - check amount of data in fifo registers... */ +@@ -2207,7 +2209,7 @@ s3c24xx_serial_console_txrdy(struct uart + } + + static bool +-s3c24xx_port_configured(unsigned int ucon) ++s3c24xx_port_configured(u32 ucon) + { + /* consider the serial port configured if the tx/rx mode set */ + return (ucon & 0xf) != 0; +@@ -2222,7 +2224,7 @@ s3c24xx_port_configured(unsigned int uco + static int s3c24xx_serial_get_poll_char(struct uart_port *port) + { + struct s3c24xx_uart_port *ourport = to_ourport(port); +- unsigned int ufstat; ++ u32 ufstat; + + ufstat = rd_regl(port, S3C2410_UFSTAT); + if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0) +@@ -2234,8 +2236,8 @@ static int s3c24xx_serial_get_poll_char( + static void s3c24xx_serial_put_poll_char(struct uart_port *port, + unsigned char c) + { +- unsigned int ufcon = rd_regl(port, S3C2410_UFCON); +- unsigned int ucon = rd_regl(port, S3C2410_UCON); ++ u32 ufcon = rd_regl(port, S3C2410_UFCON); ++ u32 ucon = rd_regl(port, S3C2410_UCON); + + /* not possible to xmit on unconfigured port */ + if (!s3c24xx_port_configured(ucon)) +@@ -2251,7 +2253,7 @@ static void s3c24xx_serial_put_poll_char + static void + s3c24xx_serial_console_putchar(struct uart_port *port, int ch) + { +- unsigned int ufcon = rd_regl(port, S3C2410_UFCON); ++ u32 ufcon = rd_regl(port, S3C2410_UFCON); + + while (!s3c24xx_serial_console_txrdy(port, ufcon)) + cpu_relax(); +@@ -2262,7 +2264,7 @@ static void + s3c24xx_serial_console_write(struct console *co, const char *s, + unsigned int count) + { +- unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); ++ u32 ucon = rd_regl(cons_uart, S3C2410_UCON); + + /* not possible to xmit on unconfigured port */ + if (!s3c24xx_port_configured(ucon)) +@@ -2276,11 +2278,9 @@ s3c24xx_serial_get_options(struct uart_p + int *parity, int *bits) + { + struct clk *clk; +- unsigned int ulcon; +- unsigned int ucon; +- unsigned int ubrdiv; + unsigned long rate; + unsigned int clk_sel; ++ u32 ulcon, ucon, ubrdiv; + char clk_name[MAX_CLK_NAME_LENGTH]; + + ulcon = rd_regl(port, S3C2410_ULCON); +@@ -2677,6 +2677,7 @@ static void samsung_early_write(struct c + uart_console_write(&dev->port, s, n, samsung_early_putc); + } + ++ + static int __init samsung_early_console_setup(struct earlycon_device *device, + const char *opt) + { diff --git a/queue-5.10/usb-cdns3-gadget-fix-request-skipping-after-clearing-halt.patch b/queue-5.10/usb-cdns3-gadget-fix-request-skipping-after-clearing-halt.patch new file mode 100644 index 0000000000..ccea523ad0 --- /dev/null +++ b/queue-5.10/usb-cdns3-gadget-fix-request-skipping-after-clearing-halt.patch @@ -0,0 +1,71 @@ +From sashal@kernel.org Fri Jun 5 01:15:06 2026 +From: Sasha Levin +Date: Thu, 4 Jun 2026 15:45:00 -0400 +Subject: usb: cdns3: gadget: fix request skipping after clearing halt +To: stable@vger.kernel.org +Cc: Yongchao Wu , stable , Peter Chen , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260604194501.920866-1-sashal@kernel.org> + +From: Yongchao Wu + +[ Upstream commit c8778ff817a7047d6848fefba99dcb27b1bf01fe ] + +According to the cdns3 datasheet, the EPRST (Endpoint Reset) command +causes the DMA engine to reposition its internal pointer to the next +Transfer Descriptor (TD) if it was already processing one. + +This issue is consistently observed during the ADB identification +process on macOS hosts, where the host issues a Clear_Halt. Although +commit 4bf2dd65135a ("usb: cdns3: gadget: toggle cycle bit before reset +endpoint") attempted to avoid DMA advance by toggling the cycle bit, +trace logs show that on certain hosts like macOS, the DMA pointer +(EP_TRADDR) still shifts after EPRST: + + cdns3_ctrl_req: Clear Endpoint Feature(Halt ep1out) + cdns3_doorbell_epx: ep1out, ep_trbaddr f9c04030 <-- Should be f9c04000 + cdns3_gadget_giveback: ep1out: req: ... length: 16384/16384 + +As shown above, the DMA pointer jumped to the next TD, causing +the controller to skip the initial TRBs of the request. This leads to +data misalignment and ADB protocol hangs on macOS. + +Fix this by manually restoring the EP_TRADDR register to the starting +physical address of the current request after the EPRST operation is +complete. + +Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver") +Cc: stable +Cc: Peter Chen +Signed-off-by: Yongchao Wu +Acked-by: Peter Chen +Link: https://patch.msgid.link/20260513160012.2547894-1-yongchao.wu@autochips.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/cdns3/gadget.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/usb/cdns3/gadget.c ++++ b/drivers/usb/cdns3/gadget.c +@@ -2798,9 +2798,19 @@ int __cdns3_gadget_ep_clear_halt(struct + priv_ep->flags &= ~(EP_STALLED | EP_STALL_PENDING); + + if (request) { +- if (trb) ++ if (trb) { + *trb = trb_tmp; + ++ /* ++ * Per datasheet, EPRST causes DMA to reposition to the next TD. ++ * Manually reset EP_TRADDR to the current TRB to prevent ++ * the hardware from skipping the interrupted request. ++ */ ++ writel(EP_TRADDR_TRADDR(priv_ep->trb_pool_dma + ++ priv_req->start_trb * TRB_SIZE), ++ &priv_dev->regs->ep_traddr); ++ } ++ + cdns3_rearm_transfer(priv_ep, 1); + } + diff --git a/queue-5.10/usb-gadget-f_hid-fix-device-reference-leak-in-hidg_alloc.patch b/queue-5.10/usb-gadget-f_hid-fix-device-reference-leak-in-hidg_alloc.patch new file mode 100644 index 0000000000..ff6267a138 --- /dev/null +++ b/queue-5.10/usb-gadget-f_hid-fix-device-reference-leak-in-hidg_alloc.patch @@ -0,0 +1,58 @@ +From stable+bounces-260813-greg=kroah.com@vger.kernel.org Sat Jun 6 01:16:30 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 15:46:20 -0400 +Subject: usb: gadget: f_hid: fix device reference leak in hidg_alloc() +To: stable@vger.kernel.org +Cc: Guangshuo Li , stable , Johan Hovold , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605194620.2186017-2-sashal@kernel.org> + +From: Guangshuo Li + +[ Upstream commit 4f88d65def6f3c90121601b4f62a4c967f3063a6 ] + +hidg_alloc() initializes hidg->dev with device_initialize() before +calling dev_set_name(). If dev_set_name() fails, the function currently +jumps to err_unlock and returns without calling put_device(). + +This leaves the device reference unbalanced and prevents hidg_release() +from being called. Calling put_device() here is also safe, since +hidg_release() only frees resources owned by hidg. + +The issue was identified by a static analysis tool I developed and +confirmed by manual review. + +Route the dev_set_name() failure path through err_put_device so the +device reference is dropped properly. + +Fixes: 89ff3dfac604 ("usb: gadget: f_hid: fix f_hidg lifetime vs cdev") +Cc: stable +Reviewed-by: Johan Hovold +Signed-off-by: Guangshuo Li +Reviewed-by: Johan Hovold johan@kernel.org +Link: https://patch.msgid.link/20260413142119.2977716-1-lgs201920130244@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_hid.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -1278,7 +1278,7 @@ static struct usb_function *hidg_alloc(s + hidg->dev.devt = MKDEV(major, opts->minor); + ret = dev_set_name(&hidg->dev, "hidg%d", opts->minor); + if (ret) +- goto err_unlock; ++ goto err_put_device; + + hidg->bInterfaceSubClass = opts->subclass; + hidg->bInterfaceProtocol = opts->protocol; +@@ -1313,7 +1313,6 @@ static struct usb_function *hidg_alloc(s + + err_put_device: + put_device(&hidg->dev); +-err_unlock: + mutex_unlock(&opts->lock); + return ERR_PTR(ret); + } diff --git a/queue-5.10/usb-gadget-f_hid-tidy-error-handling-in-hidg_alloc.patch b/queue-5.10/usb-gadget-f_hid-tidy-error-handling-in-hidg_alloc.patch new file mode 100644 index 0000000000..a241a196b1 --- /dev/null +++ b/queue-5.10/usb-gadget-f_hid-tidy-error-handling-in-hidg_alloc.patch @@ -0,0 +1,87 @@ +From stable+bounces-260812-greg=kroah.com@vger.kernel.org Sat Jun 6 01:16:31 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 15:46:19 -0400 +Subject: usb: gadget: f_hid: tidy error handling in hidg_alloc +To: stable@vger.kernel.org +Cc: John Keeping , Lee Jones , Andrzej Pietrasiewicz , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260605194620.2186017-1-sashal@kernel.org> + +From: John Keeping + +[ Upstream commit 944fe915d00d3cb1bacb1e77cabfb6dc82e6f8b8 ] + +Unify error handling at the end of the function, reducing the risk of +missing something on one of the error paths. + +Moving the increment of opts->refcnt later means there is no need to +decrement it on the error path and is safe as this is guarded by +opts->lock which is held for this entire section. + +Tested-by: Lee Jones +Reviewed-by: Andrzej Pietrasiewicz +Reviewed-by: Lee Jones +Signed-off-by: John Keeping +Link: https://lore.kernel.org/r/20221122123523.3068034-4-john@metanate.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 4f88d65def6f ("usb: gadget: f_hid: fix device reference leak in hidg_alloc()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_hid.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -1265,7 +1265,6 @@ static struct usb_function *hidg_alloc(s + opts = container_of(fi, struct f_hid_opts, func_inst); + + mutex_lock(&opts->lock); +- ++opts->refcnt; + + spin_lock_init(&hidg->write_spinlock); + spin_lock_init(&hidg->read_spinlock); +@@ -1278,11 +1277,8 @@ static struct usb_function *hidg_alloc(s + hidg->dev.class = hidg_class; + hidg->dev.devt = MKDEV(major, opts->minor); + ret = dev_set_name(&hidg->dev, "hidg%d", opts->minor); +- if (ret) { +- --opts->refcnt; +- mutex_unlock(&opts->lock); +- return ERR_PTR(ret); +- } ++ if (ret) ++ goto err_unlock; + + hidg->bInterfaceSubClass = opts->subclass; + hidg->bInterfaceProtocol = opts->protocol; +@@ -1293,14 +1289,13 @@ static struct usb_function *hidg_alloc(s + opts->report_desc_length, + GFP_KERNEL); + if (!hidg->report_desc) { +- put_device(&hidg->dev); +- --opts->refcnt; +- mutex_unlock(&opts->lock); +- return ERR_PTR(-ENOMEM); ++ ret = -ENOMEM; ++ goto err_put_device; + } + } + hidg->use_out_ep = !opts->no_out_endpoint; + ++ ++opts->refcnt; + mutex_unlock(&opts->lock); + + hidg->func.name = "hid"; +@@ -1315,6 +1310,12 @@ static struct usb_function *hidg_alloc(s + hidg->qlen = 4; + + return &hidg->func; ++ ++err_put_device: ++ put_device(&hidg->dev); ++err_unlock: ++ mutex_unlock(&opts->lock); ++ return ERR_PTR(ret); + } + + DECLARE_USB_FUNCTION_INIT(hid, hidg_alloc_inst, hidg_alloc); diff --git a/queue-5.10/xfrm-input-hold-netns-during-deferred-transport-reinjection.patch b/queue-5.10/xfrm-input-hold-netns-during-deferred-transport-reinjection.patch new file mode 100644 index 0000000000..e8789609cf --- /dev/null +++ b/queue-5.10/xfrm-input-hold-netns-during-deferred-transport-reinjection.patch @@ -0,0 +1,79 @@ +From stable+bounces-260691-greg=kroah.com@vger.kernel.org Fri Jun 5 18:36:41 2026 +From: Sasha Levin +Date: Fri, 5 Jun 2026 09:05:13 -0400 +Subject: xfrm: input: hold netns during deferred transport reinjection +To: stable@vger.kernel.org +Cc: Zhengchuan Liang , stable@kernel.org, Yuan Tan , Xin Liu , Luxing Yin , Ren Wei , Steffen Klassert , Sasha Levin +Message-ID: <20260605130513.410471-1-sashal@kernel.org> + +From: Zhengchuan Liang + +[ Upstream commit c16f74dc1d75d0e2e7670076d5375deda110ebeb ] + +Transport-mode reinjection stores a struct net pointer in skb->cb and +uses it later from xfrm_trans_reinject(). That pointer must stay valid +until the deferred callback runs. + +Take a netns reference when queueing deferred reinjection work and drop +it after the callback completes. Use maybe_get_net() so the queueing +path does not revive a namespace that is already being torn down. + +This keeps the existing workqueue design and fixes the netns lifetime +handling in one place for all users of xfrm_trans_queue_net(). + +Fixes: 7b3801927e52 ("xfrm: introduce xfrm_trans_queue_net") +Cc: stable@kernel.org +Reported-by: Yuan Tan +Reported-by: Xin Liu +Co-developed-by: Luxing Yin +Signed-off-by: Luxing Yin +Signed-off-by: Zhengchuan Liang +Signed-off-by: Ren Wei +Assisted-by: Codex:gpt-5.4 +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/xfrm_input.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +--- a/net/xfrm/xfrm_input.c ++++ b/net/xfrm/xfrm_input.c +@@ -777,9 +777,12 @@ static void xfrm_trans_reinject(unsigned + __skb_queue_head_init(&queue); + skb_queue_splice_init(&trans->queue, &queue); + +- while ((skb = __skb_dequeue(&queue))) +- XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net, +- NULL, skb); ++ while ((skb = __skb_dequeue(&queue))) { ++ struct net *net = XFRM_TRANS_SKB_CB(skb)->net; ++ ++ XFRM_TRANS_SKB_CB(skb)->finish(net, NULL, skb); ++ put_net(net); ++ } + } + + int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, +@@ -787,6 +790,7 @@ int xfrm_trans_queue_net(struct net *net + struct sk_buff *)) + { + struct xfrm_trans_tasklet *trans; ++ struct net *hold_net; + + trans = this_cpu_ptr(&xfrm_trans_tasklet); + +@@ -795,8 +799,12 @@ int xfrm_trans_queue_net(struct net *net + + BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb)); + ++ hold_net = maybe_get_net(net); ++ if (!hold_net) ++ return -ENODEV; ++ + XFRM_TRANS_SKB_CB(skb)->finish = finish; +- XFRM_TRANS_SKB_CB(skb)->net = net; ++ XFRM_TRANS_SKB_CB(skb)->net = hold_net; + __skb_queue_tail(&trans->queue, skb); + tasklet_schedule(&trans->tasklet); + return 0;