From 566da90a2e72a8f629cf7bf553669546488d3c0a Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 26 Jan 2024 09:04:45 -0500 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...ll-pointer-in-channel-unregistration.patch | 55 ++++ ...allow-users-to-configure-device-even.patch | 295 ++++++++++++++++++ ...enable-internal-vref-if-external-vre.patch | 67 ++++ ...91r-set-alert-bit-in-config-register.patch | 53 ++++ ...llow-o_trunc-open-on-read-only-share.patch | 88 ++++++ ...af-issue-in-ksmbd_tcp_new_connection.patch | 119 +++++++ ...e-ppace-array-on-error-in-parse_dacl.patch | 61 ++++ ...-only-v2-leases-handle-the-directory.patch | 42 +++ ...validate-mech-token-in-session-setup.patch | 113 +++++++ ...move-the-ufshcd_hba_exit-call-from-u.patch | 48 +++ ...mplify-power-management-during-async.patch | 60 ++++ queue-5.15/series | 11 + 12 files changed, 1012 insertions(+) create mode 100644 queue-5.15/dmaengine-fix-null-pointer-in-channel-unregistration.patch create mode 100644 queue-5.15/iio-adc-ad7091r-allow-users-to-configure-device-even.patch create mode 100644 queue-5.15/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch create mode 100644 queue-5.15/iio-adc-ad7091r-set-alert-bit-in-config-register.patch create mode 100644 queue-5.15/ksmbd-don-t-allow-o_trunc-open-on-read-only-share.patch create mode 100644 queue-5.15/ksmbd-fix-uaf-issue-in-ksmbd_tcp_new_connection.patch create mode 100644 queue-5.15/ksmbd-free-ppace-array-on-error-in-parse_dacl.patch create mode 100644 queue-5.15/ksmbd-only-v2-leases-handle-the-directory.patch create mode 100644 queue-5.15/ksmbd-validate-mech-token-in-session-setup.patch create mode 100644 queue-5.15/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch create mode 100644 queue-5.15/scsi-ufs-core-simplify-power-management-during-async.patch create mode 100644 queue-5.15/series diff --git a/queue-5.15/dmaengine-fix-null-pointer-in-channel-unregistration.patch b/queue-5.15/dmaengine-fix-null-pointer-in-channel-unregistration.patch new file mode 100644 index 00000000000..63e8c53bddd --- /dev/null +++ b/queue-5.15/dmaengine-fix-null-pointer-in-channel-unregistration.patch @@ -0,0 +1,55 @@ +From 96cb3f4144b769a8f2be6f70258a0fee4d2ca9e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Dec 2023 17:04:52 +0100 +Subject: dmaengine: fix NULL pointer in channel unregistration function + +From: Amelie Delaunay + +[ Upstream commit f5c24d94512f1b288262beda4d3dcb9629222fc7 ] + +__dma_async_device_channel_register() can fail. In case of failure, +chan->local is freed (with free_percpu()), and chan->local is nullified. +When dma_async_device_unregister() is called (because of managed API or +intentionally by DMA controller driver), channels are unconditionally +unregistered, leading to this NULL pointer: +[ 1.318693] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000d0 +[...] +[ 1.484499] Call trace: +[ 1.486930] device_del+0x40/0x394 +[ 1.490314] device_unregister+0x20/0x7c +[ 1.494220] __dma_async_device_channel_unregister+0x68/0xc0 + +Look at dma_async_device_register() function error path, channel device +unregistration is done only if chan->local is not NULL. + +Then add the same condition at the beginning of +__dma_async_device_channel_unregister() function, to avoid NULL pointer +issue whatever the API used to reach this function. + +Fixes: d2fb0a043838 ("dmaengine: break out channel registration") +Signed-off-by: Amelie Delaunay +Reviewed-by: Dave Jiang +Link: https://lore.kernel.org/r/20231213160452.2598073-1-amelie.delaunay@foss.st.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/dmaengine.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c +index 4ec7bb58c195..9559ebd61f3b 100644 +--- a/drivers/dma/dmaengine.c ++++ b/drivers/dma/dmaengine.c +@@ -1108,6 +1108,9 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_register); + static void __dma_async_device_channel_unregister(struct dma_device *device, + struct dma_chan *chan) + { ++ if (chan->local == NULL) ++ return; ++ + WARN_ONCE(!device->device_release && chan->client_count, + "%s called while %d clients hold a reference\n", + __func__, chan->client_count); +-- +2.43.0 + diff --git a/queue-5.15/iio-adc-ad7091r-allow-users-to-configure-device-even.patch b/queue-5.15/iio-adc-ad7091r-allow-users-to-configure-device-even.patch new file mode 100644 index 00000000000..99de4a0e4cd --- /dev/null +++ b/queue-5.15/iio-adc-ad7091r-allow-users-to-configure-device-even.patch @@ -0,0 +1,295 @@ +From e9662ff8cda944ff625e9caa70179ccdfc1deb2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 17:26:01 -0300 +Subject: iio: adc: ad7091r: Allow users to configure device events + +From: Marcelo Schmitt + +[ Upstream commit 020e71c7ffc25dfe29ed9be6c2d39af7bd7f661f ] + +AD7091R-5 devices are supported by the ad7091r-5 driver together with +the ad7091r-base driver. Those drivers declared iio events for notifying +user space when ADC readings fall bellow the thresholds of low limit +registers or above the values set in high limit registers. +However, to configure iio events and their thresholds, a set of callback +functions must be implemented and those were not present until now. +The consequence of trying to configure ad7091r-5 events without the +proper callback functions was a null pointer dereference in the kernel +because the pointers to the callback functions were not set. + +Implement event configuration callbacks allowing users to read/write +event thresholds and enable/disable event generation. + +Since the event spec structs are generic to AD7091R devices, also move +those from the ad7091r-5 driver the base driver so they can be reused +when support for ad7091r-2/-4/-8 be added. + +Fixes: ca69300173b6 ("iio: adc: Add support for AD7091R5 ADC") +Suggested-by: David Lechner +Signed-off-by: Marcelo Schmitt +Link: https://lore.kernel.org/r/59552d3548dabd56adc3107b7b4869afee2b0c3c.1703013352.git.marcelo.schmitt1@gmail.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7091r-base.c | 156 +++++++++++++++++++++++++++++++++ + drivers/iio/adc/ad7091r-base.h | 6 ++ + drivers/iio/adc/ad7091r5.c | 28 +----- + 3 files changed, 166 insertions(+), 24 deletions(-) + +diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c +index ad089c0ff953..9ddda08918db 100644 +--- a/drivers/iio/adc/ad7091r-base.c ++++ b/drivers/iio/adc/ad7091r-base.c +@@ -6,6 +6,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -50,6 +51,27 @@ struct ad7091r_state { + struct mutex lock; /*lock to prevent concurent reads */ + }; + ++const struct iio_event_spec ad7091r_events[] = { ++ { ++ .type = IIO_EV_TYPE_THRESH, ++ .dir = IIO_EV_DIR_RISING, ++ .mask_separate = BIT(IIO_EV_INFO_VALUE) | ++ BIT(IIO_EV_INFO_ENABLE), ++ }, ++ { ++ .type = IIO_EV_TYPE_THRESH, ++ .dir = IIO_EV_DIR_FALLING, ++ .mask_separate = BIT(IIO_EV_INFO_VALUE) | ++ BIT(IIO_EV_INFO_ENABLE), ++ }, ++ { ++ .type = IIO_EV_TYPE_THRESH, ++ .dir = IIO_EV_DIR_EITHER, ++ .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), ++ }, ++}; ++EXPORT_SYMBOL_NS_GPL(ad7091r_events, IIO_AD7091R); ++ + static int ad7091r_set_mode(struct ad7091r_state *st, enum ad7091r_mode mode) + { + int ret, conf; +@@ -169,8 +191,142 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev, + return ret; + } + ++static int ad7091r_read_event_config(struct iio_dev *indio_dev, ++ const struct iio_chan_spec *chan, ++ enum iio_event_type type, ++ enum iio_event_direction dir) ++{ ++ struct ad7091r_state *st = iio_priv(indio_dev); ++ int val, ret; ++ ++ switch (dir) { ++ case IIO_EV_DIR_RISING: ++ ret = regmap_read(st->map, ++ AD7091R_REG_CH_HIGH_LIMIT(chan->channel), ++ &val); ++ if (ret) ++ return ret; ++ return val != AD7091R_HIGH_LIMIT; ++ case IIO_EV_DIR_FALLING: ++ ret = regmap_read(st->map, ++ AD7091R_REG_CH_LOW_LIMIT(chan->channel), ++ &val); ++ if (ret) ++ return ret; ++ return val != AD7091R_LOW_LIMIT; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ad7091r_write_event_config(struct iio_dev *indio_dev, ++ const struct iio_chan_spec *chan, ++ enum iio_event_type type, ++ enum iio_event_direction dir, int state) ++{ ++ struct ad7091r_state *st = iio_priv(indio_dev); ++ ++ if (state) { ++ return regmap_set_bits(st->map, AD7091R_REG_CONF, ++ AD7091R_REG_CONF_ALERT_EN); ++ } else { ++ /* ++ * Set thresholds either to 0 or to 2^12 - 1 as appropriate to ++ * prevent alerts and thus disable event generation. ++ */ ++ switch (dir) { ++ case IIO_EV_DIR_RISING: ++ return regmap_write(st->map, ++ AD7091R_REG_CH_HIGH_LIMIT(chan->channel), ++ AD7091R_HIGH_LIMIT); ++ case IIO_EV_DIR_FALLING: ++ return regmap_write(st->map, ++ AD7091R_REG_CH_LOW_LIMIT(chan->channel), ++ AD7091R_LOW_LIMIT); ++ default: ++ return -EINVAL; ++ } ++ } ++} ++ ++static int ad7091r_read_event_value(struct iio_dev *indio_dev, ++ const struct iio_chan_spec *chan, ++ enum iio_event_type type, ++ enum iio_event_direction dir, ++ enum iio_event_info info, int *val, int *val2) ++{ ++ struct ad7091r_state *st = iio_priv(indio_dev); ++ int ret; ++ ++ switch (info) { ++ case IIO_EV_INFO_VALUE: ++ switch (dir) { ++ case IIO_EV_DIR_RISING: ++ ret = regmap_read(st->map, ++ AD7091R_REG_CH_HIGH_LIMIT(chan->channel), ++ val); ++ if (ret) ++ return ret; ++ return IIO_VAL_INT; ++ case IIO_EV_DIR_FALLING: ++ ret = regmap_read(st->map, ++ AD7091R_REG_CH_LOW_LIMIT(chan->channel), ++ val); ++ if (ret) ++ return ret; ++ return IIO_VAL_INT; ++ default: ++ return -EINVAL; ++ } ++ case IIO_EV_INFO_HYSTERESIS: ++ ret = regmap_read(st->map, ++ AD7091R_REG_CH_HYSTERESIS(chan->channel), ++ val); ++ if (ret) ++ return ret; ++ return IIO_VAL_INT; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ad7091r_write_event_value(struct iio_dev *indio_dev, ++ const struct iio_chan_spec *chan, ++ enum iio_event_type type, ++ enum iio_event_direction dir, ++ enum iio_event_info info, int val, int val2) ++{ ++ struct ad7091r_state *st = iio_priv(indio_dev); ++ ++ switch (info) { ++ case IIO_EV_INFO_VALUE: ++ switch (dir) { ++ case IIO_EV_DIR_RISING: ++ return regmap_write(st->map, ++ AD7091R_REG_CH_HIGH_LIMIT(chan->channel), ++ val); ++ case IIO_EV_DIR_FALLING: ++ return regmap_write(st->map, ++ AD7091R_REG_CH_LOW_LIMIT(chan->channel), ++ val); ++ default: ++ return -EINVAL; ++ } ++ case IIO_EV_INFO_HYSTERESIS: ++ return regmap_write(st->map, ++ AD7091R_REG_CH_HYSTERESIS(chan->channel), ++ val); ++ default: ++ return -EINVAL; ++ } ++} ++ + static const struct iio_info ad7091r_info = { + .read_raw = ad7091r_read_raw, ++ .read_event_config = &ad7091r_read_event_config, ++ .write_event_config = &ad7091r_write_event_config, ++ .read_event_value = &ad7091r_read_event_value, ++ .write_event_value = &ad7091r_write_event_value, + }; + + static irqreturn_t ad7091r_event_handler(int irq, void *private) +diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h +index 509748aef9b1..7a78976a2f80 100644 +--- a/drivers/iio/adc/ad7091r-base.h ++++ b/drivers/iio/adc/ad7091r-base.h +@@ -8,6 +8,10 @@ + #ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__ + #define __DRIVERS_IIO_ADC_AD7091R_BASE_H__ + ++/* AD7091R_REG_CH_LIMIT */ ++#define AD7091R_HIGH_LIMIT 0xFFF ++#define AD7091R_LOW_LIMIT 0x0 ++ + struct device; + struct ad7091r_state; + +@@ -17,6 +21,8 @@ struct ad7091r_chip_info { + unsigned int vref_mV; + }; + ++extern const struct iio_event_spec ad7091r_events[3]; ++ + extern const struct regmap_config ad7091r_regmap_config; + + int ad7091r_probe(struct device *dev, const char *name, +diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c +index 9665679c3ea6..e60511460786 100644 +--- a/drivers/iio/adc/ad7091r5.c ++++ b/drivers/iio/adc/ad7091r5.c +@@ -12,26 +12,6 @@ + + #include "ad7091r-base.h" + +-static const struct iio_event_spec ad7091r5_events[] = { +- { +- .type = IIO_EV_TYPE_THRESH, +- .dir = IIO_EV_DIR_RISING, +- .mask_separate = BIT(IIO_EV_INFO_VALUE) | +- BIT(IIO_EV_INFO_ENABLE), +- }, +- { +- .type = IIO_EV_TYPE_THRESH, +- .dir = IIO_EV_DIR_FALLING, +- .mask_separate = BIT(IIO_EV_INFO_VALUE) | +- BIT(IIO_EV_INFO_ENABLE), +- }, +- { +- .type = IIO_EV_TYPE_THRESH, +- .dir = IIO_EV_DIR_EITHER, +- .mask_separate = BIT(IIO_EV_INFO_HYSTERESIS), +- }, +-}; +- + #define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +@@ -44,10 +24,10 @@ static const struct iio_event_spec ad7091r5_events[] = { + .scan_type.realbits = bits, \ + } + static const struct iio_chan_spec ad7091r5_channels_irq[] = { +- AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), +- AD7091R_CHANNEL(1, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), +- AD7091R_CHANNEL(2, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), +- AD7091R_CHANNEL(3, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), ++ AD7091R_CHANNEL(0, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)), ++ AD7091R_CHANNEL(1, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)), ++ AD7091R_CHANNEL(2, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)), ++ AD7091R_CHANNEL(3, 12, ad7091r_events, ARRAY_SIZE(ad7091r_events)), + }; + + static const struct iio_chan_spec ad7091r5_channels_noirq[] = { +-- +2.43.0 + diff --git a/queue-5.15/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch b/queue-5.15/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch new file mode 100644 index 00000000000..dec62c1ad07 --- /dev/null +++ b/queue-5.15/iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch @@ -0,0 +1,67 @@ +From b273ec67f727a8c8243c2119b907dba4db09dfaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 17:26:27 -0300 +Subject: iio: adc: ad7091r: Enable internal vref if external vref is not + supplied + +From: Marcelo Schmitt + +[ Upstream commit e71c5c89bcb165a02df35325aa13d1ee40112401 ] + +The ADC needs a voltage reference to work correctly. +Users can provide an external voltage reference or use the chip internal +reference to operate the ADC. +The availability of an in chip reference for the ADC saves the user from +having to supply an external voltage reference, which makes the external +reference an optional property as described in the device tree +documentation. +Though, to use the internal reference, it must be enabled by writing to +the configuration register. +Enable AD7091R internal voltage reference if no external vref is supplied. + +Fixes: 260442cc5be4 ("iio: adc: ad7091r5: Add scale and external VREF support") +Signed-off-by: Marcelo Schmitt +Link: https://lore.kernel.org/r/b865033fa6a4fc4bf2b4a98ec51a6144e0f64f77.1703013352.git.marcelo.schmitt1@gmail.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7091r-base.c | 7 +++++++ + drivers/iio/adc/ad7091r-base.h | 2 ++ + 2 files changed, 9 insertions(+) + +diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c +index 9ddda08918db..f345542e69a0 100644 +--- a/drivers/iio/adc/ad7091r-base.c ++++ b/drivers/iio/adc/ad7091r-base.c +@@ -405,7 +405,14 @@ int ad7091r_probe(struct device *dev, const char *name, + if (IS_ERR(st->vref)) { + if (PTR_ERR(st->vref) == -EPROBE_DEFER) + return -EPROBE_DEFER; ++ + st->vref = NULL; ++ /* Enable internal vref */ ++ ret = regmap_set_bits(st->map, AD7091R_REG_CONF, ++ AD7091R_REG_CONF_INT_VREF); ++ if (ret) ++ return dev_err_probe(st->dev, ret, ++ "Error on enable internal reference\n"); + } else { + ret = regulator_enable(st->vref); + if (ret) +diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h +index 7a78976a2f80..b9e1c8bf3440 100644 +--- a/drivers/iio/adc/ad7091r-base.h ++++ b/drivers/iio/adc/ad7091r-base.h +@@ -8,6 +8,8 @@ + #ifndef __DRIVERS_IIO_ADC_AD7091R_BASE_H__ + #define __DRIVERS_IIO_ADC_AD7091R_BASE_H__ + ++#define AD7091R_REG_CONF_INT_VREF BIT(0) ++ + /* AD7091R_REG_CH_LIMIT */ + #define AD7091R_HIGH_LIMIT 0xFFF + #define AD7091R_LOW_LIMIT 0x0 +-- +2.43.0 + diff --git a/queue-5.15/iio-adc-ad7091r-set-alert-bit-in-config-register.patch b/queue-5.15/iio-adc-ad7091r-set-alert-bit-in-config-register.patch new file mode 100644 index 00000000000..bb560df7a11 --- /dev/null +++ b/queue-5.15/iio-adc-ad7091r-set-alert-bit-in-config-register.patch @@ -0,0 +1,53 @@ +From 5de8b4a35c2e197a464adcf6b6a89276a4809f03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Dec 2023 14:46:37 -0300 +Subject: iio: adc: ad7091r: Set alert bit in config register + +From: Marcelo Schmitt + +[ Upstream commit 149694f5e79b0c7a36ceb76e7c0d590db8f151c1 ] + +The ad7091r-base driver sets up an interrupt handler for firing events +when inputs are either above or below a certain threshold. +However, for the interrupt signal to come from the device it must be +configured to enable the ALERT/BUSY/GPO pin to be used as ALERT, which +was not being done until now. +Enable interrupt signals on the ALERT/BUSY/GPO pin by setting the proper +bit in the configuration register. + +Signed-off-by: Marcelo Schmitt +Link: https://lore.kernel.org/r/e8da2ee98d6df88318b14baf3dc9630e20218418.1702746240.git.marcelo.schmitt1@gmail.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 020e71c7ffc2 ("iio: adc: ad7091r: Allow users to configure device events") +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/ad7091r-base.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c +index 811f04448d8d..ad089c0ff953 100644 +--- a/drivers/iio/adc/ad7091r-base.c ++++ b/drivers/iio/adc/ad7091r-base.c +@@ -28,6 +28,7 @@ + #define AD7091R_REG_RESULT_CONV_RESULT(x) ((x) & 0xfff) + + /* AD7091R_REG_CONF */ ++#define AD7091R_REG_CONF_ALERT_EN BIT(4) + #define AD7091R_REG_CONF_AUTO BIT(8) + #define AD7091R_REG_CONF_CMD BIT(10) + +@@ -232,6 +233,11 @@ int ad7091r_probe(struct device *dev, const char *name, + iio_dev->channels = chip_info->channels; + + if (irq) { ++ ret = regmap_update_bits(st->map, AD7091R_REG_CONF, ++ AD7091R_REG_CONF_ALERT_EN, BIT(4)); ++ if (ret) ++ return ret; ++ + ret = devm_request_threaded_irq(dev, irq, NULL, + ad7091r_event_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, iio_dev); +-- +2.43.0 + diff --git a/queue-5.15/ksmbd-don-t-allow-o_trunc-open-on-read-only-share.patch b/queue-5.15/ksmbd-don-t-allow-o_trunc-open-on-read-only-share.patch new file mode 100644 index 00000000000..50093b2917f --- /dev/null +++ b/queue-5.15/ksmbd-don-t-allow-o_trunc-open-on-read-only-share.patch @@ -0,0 +1,88 @@ +From a08fe1e40643df94e72b388207decc360196e578 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 7 Jan 2024 21:24:07 +0900 +Subject: ksmbd: don't allow O_TRUNC open on read-only share + +From: Namjae Jeon + +[ Upstream commit d592a9158a112d419f341f035d18d02f8d232def ] + +When file is changed using notepad on read-only share(read_only = yes in +ksmbd.conf), There is a problem where existing data is truncated. +notepad in windows try to O_TRUNC open(FILE_OVERWRITE_IF) and all data +in file is truncated. This patch don't allow O_TRUNC open on read-only +share and add KSMBD_TREE_CONN_FLAG_WRITABLE check in smb2_set_info(). + +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/smb2pdu.c | 23 +++++++++-------------- + 1 file changed, 9 insertions(+), 14 deletions(-) + +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index 8875c04e8382..bf3bb37c00a9 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -2968,7 +2968,7 @@ int smb2_open(struct ksmbd_work *work) + &may_flags); + + if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { +- if (open_flags & O_CREAT) { ++ if (open_flags & (O_CREAT | O_TRUNC)) { + ksmbd_debug(SMB, + "User does not have write permission\n"); + rc = -EACCES; +@@ -5945,12 +5945,6 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, + } + case FILE_RENAME_INFORMATION: + { +- if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { +- ksmbd_debug(SMB, +- "User does not have write permission\n"); +- return -EACCES; +- } +- + if (buf_len < sizeof(struct smb2_file_rename_info)) + return -EINVAL; + +@@ -5970,12 +5964,6 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, + } + case FILE_DISPOSITION_INFORMATION: + { +- if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { +- ksmbd_debug(SMB, +- "User does not have write permission\n"); +- return -EACCES; +- } +- + if (buf_len < sizeof(struct smb2_file_disposition_info)) + return -EINVAL; + +@@ -6037,7 +6025,7 @@ int smb2_set_info(struct ksmbd_work *work) + { + struct smb2_set_info_req *req; + struct smb2_set_info_rsp *rsp; +- struct ksmbd_file *fp; ++ struct ksmbd_file *fp = NULL; + int rc = 0; + unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID; + +@@ -6057,6 +6045,13 @@ int smb2_set_info(struct ksmbd_work *work) + rsp = smb2_get_msg(work->response_buf); + } + ++ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { ++ ksmbd_debug(SMB, "User does not have write permission\n"); ++ pr_err("User does not have write permission\n"); ++ rc = -EACCES; ++ goto err_out; ++ } ++ + if (!has_file_id(id)) { + id = req->VolatileFileId; + pid = req->PersistentFileId; +-- +2.43.0 + diff --git a/queue-5.15/ksmbd-fix-uaf-issue-in-ksmbd_tcp_new_connection.patch b/queue-5.15/ksmbd-fix-uaf-issue-in-ksmbd_tcp_new_connection.patch new file mode 100644 index 00000000000..cd6a7efb968 --- /dev/null +++ b/queue-5.15/ksmbd-fix-uaf-issue-in-ksmbd_tcp_new_connection.patch @@ -0,0 +1,119 @@ +From 2231681d45102750c6c236afcbea1823b5102688 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Jan 2024 15:30:07 +0900 +Subject: ksmbd: fix UAF issue in ksmbd_tcp_new_connection() + +From: Namjae Jeon + +[ Upstream commit 38d20c62903d669693a1869aa68c4dd5674e2544 ] + +The race is between the handling of a new TCP connection and +its disconnection. It leads to UAF on `struct tcp_transport` in +ksmbd_tcp_new_connection() function. + +Cc: stable@vger.kernel.org +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-22991 +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/connection.c | 6 ------ + fs/ksmbd/connection.h | 1 - + fs/ksmbd/transport_rdma.c | 11 ++++++----- + fs/ksmbd/transport_tcp.c | 13 +++++++------ + 4 files changed, 13 insertions(+), 18 deletions(-) + +diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c +index 0a7a30bd531f..3db9c06c946d 100644 +--- a/fs/ksmbd/connection.c ++++ b/fs/ksmbd/connection.c +@@ -415,13 +415,7 @@ static void stop_sessions(void) + again: + down_read(&conn_list_lock); + list_for_each_entry(conn, &conn_list, conns_list) { +- struct task_struct *task; +- + t = conn->transport; +- task = t->handler; +- if (task) +- ksmbd_debug(CONN, "Stop session handler %s/%d\n", +- task->comm, task_pid_nr(task)); + ksmbd_conn_set_exiting(conn); + if (t->ops->shutdown) { + up_read(&conn_list_lock); +diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h +index 342f935f5770..0e04cf8b1d89 100644 +--- a/fs/ksmbd/connection.h ++++ b/fs/ksmbd/connection.h +@@ -135,7 +135,6 @@ struct ksmbd_transport_ops { + struct ksmbd_transport { + struct ksmbd_conn *conn; + struct ksmbd_transport_ops *ops; +- struct task_struct *handler; + }; + + #define KSMBD_TCP_RECV_TIMEOUT (7 * HZ) +diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c +index 252a1e7afcc0..355673f2830b 100644 +--- a/fs/ksmbd/transport_rdma.c ++++ b/fs/ksmbd/transport_rdma.c +@@ -2039,6 +2039,7 @@ static bool rdma_frwr_is_supported(struct ib_device_attr *attrs) + static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id) + { + struct smb_direct_transport *t; ++ struct task_struct *handler; + int ret; + + if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) { +@@ -2056,11 +2057,11 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id) + if (ret) + goto out_err; + +- KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop, +- KSMBD_TRANS(t)->conn, "ksmbd:r%u", +- smb_direct_port); +- if (IS_ERR(KSMBD_TRANS(t)->handler)) { +- ret = PTR_ERR(KSMBD_TRANS(t)->handler); ++ handler = kthread_run(ksmbd_conn_handler_loop, ++ KSMBD_TRANS(t)->conn, "ksmbd:r%u", ++ smb_direct_port); ++ if (IS_ERR(handler)) { ++ ret = PTR_ERR(handler); + pr_err("Can't start thread\n"); + goto out_err; + } +diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c +index eff7a1d793f0..9d4222154dcc 100644 +--- a/fs/ksmbd/transport_tcp.c ++++ b/fs/ksmbd/transport_tcp.c +@@ -185,6 +185,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) + struct sockaddr *csin; + int rc = 0; + struct tcp_transport *t; ++ struct task_struct *handler; + + t = alloc_transport(client_sk); + if (!t) { +@@ -199,13 +200,13 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) + goto out_error; + } + +- KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop, +- KSMBD_TRANS(t)->conn, +- "ksmbd:%u", +- ksmbd_tcp_get_port(csin)); +- if (IS_ERR(KSMBD_TRANS(t)->handler)) { ++ handler = kthread_run(ksmbd_conn_handler_loop, ++ KSMBD_TRANS(t)->conn, ++ "ksmbd:%u", ++ ksmbd_tcp_get_port(csin)); ++ if (IS_ERR(handler)) { + pr_err("cannot start conn thread\n"); +- rc = PTR_ERR(KSMBD_TRANS(t)->handler); ++ rc = PTR_ERR(handler); + free_transport(t); + } + return rc; +-- +2.43.0 + diff --git a/queue-5.15/ksmbd-free-ppace-array-on-error-in-parse_dacl.patch b/queue-5.15/ksmbd-free-ppace-array-on-error-in-parse_dacl.patch new file mode 100644 index 00000000000..4c1e5a5f7d2 --- /dev/null +++ b/queue-5.15/ksmbd-free-ppace-array-on-error-in-parse_dacl.patch @@ -0,0 +1,61 @@ +From e56c7839b6b66a1b92828131d9892cc72916c95e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jan 2024 17:14:44 +0300 +Subject: ksmbd: free ppace array on error in parse_dacl + +From: Fedor Pchelkin + +[ Upstream commit 8cf9bedfc3c47d24bb0de386f808f925dc52863e ] + +The ppace array is not freed if one of the init_acl_state() calls inside +parse_dacl() fails. At the moment the function may fail only due to the +memory allocation errors so it's highly unlikely in this case but +nevertheless a fix is needed. + +Move ppace allocation after the init_acl_state() calls with proper error +handling. + +Found by Linux Verification Center (linuxtesting.org). + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Cc: stable@vger.kernel.org +Signed-off-by: Fedor Pchelkin +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/smbacl.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c +index 9ace5027684d..3a6c0abdb035 100644 +--- a/fs/ksmbd/smbacl.c ++++ b/fs/ksmbd/smbacl.c +@@ -399,10 +399,6 @@ static void parse_dacl(struct user_namespace *user_ns, + if (num_aces > ULONG_MAX / sizeof(struct smb_ace *)) + return; + +- ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL); +- if (!ppace) +- return; +- + ret = init_acl_state(&acl_state, num_aces); + if (ret) + return; +@@ -412,6 +408,13 @@ static void parse_dacl(struct user_namespace *user_ns, + return; + } + ++ ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL); ++ if (!ppace) { ++ free_acl_state(&default_acl_state); ++ free_acl_state(&acl_state); ++ return; ++ } ++ + /* + * reset rwx permissions for user/group/other. + * Also, if num_aces is 0 i.e. DACL has no ACEs, +-- +2.43.0 + diff --git a/queue-5.15/ksmbd-only-v2-leases-handle-the-directory.patch b/queue-5.15/ksmbd-only-v2-leases-handle-the-directory.patch new file mode 100644 index 00000000000..1625be2d720 --- /dev/null +++ b/queue-5.15/ksmbd-only-v2-leases-handle-the-directory.patch @@ -0,0 +1,42 @@ +From c6b97aedd07842d019b22378b9340364df84c131 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jan 2024 10:24:54 +0900 +Subject: ksmbd: only v2 leases handle the directory + +From: Namjae Jeon + +[ Upstream commit 77bebd186442a7d703b796784db7495129cc3e70 ] + +When smb2 leases is disable, ksmbd can send oplock break notification +and cause wait oplock break ack timeout. It may appear like hang when +accessing a directory. This patch make only v2 leases handle the +directory. + +Cc: stable@vger.kernel.org +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/oplock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c +index 2da256259722..678627659803 100644 +--- a/fs/ksmbd/oplock.c ++++ b/fs/ksmbd/oplock.c +@@ -1191,6 +1191,12 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, + bool prev_op_has_lease; + __le32 prev_op_state = 0; + ++ /* Only v2 leases handle the directory */ ++ if (S_ISDIR(file_inode(fp->filp)->i_mode)) { ++ if (!lctx || lctx->version != 2) ++ return 0; ++ } ++ + opinfo = alloc_opinfo(work, pid, tid); + if (!opinfo) + return -ENOMEM; +-- +2.43.0 + diff --git a/queue-5.15/ksmbd-validate-mech-token-in-session-setup.patch b/queue-5.15/ksmbd-validate-mech-token-in-session-setup.patch new file mode 100644 index 00000000000..3513c548ae9 --- /dev/null +++ b/queue-5.15/ksmbd-validate-mech-token-in-session-setup.patch @@ -0,0 +1,113 @@ +From bd2fead30b7c4a09e64680cccdd9765b222ed657 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Jan 2024 15:11:41 +0900 +Subject: ksmbd: validate mech token in session setup + +From: Namjae Jeon + +[ Upstream commit 92e470163d96df8db6c4fa0f484e4a229edb903d ] + +If client send invalid mech token in session setup request, ksmbd +validate and make the error if it is invalid. + +Cc: stable@vger.kernel.org +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-22890 +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/asn1.c | 5 +++++ + fs/ksmbd/connection.h | 1 + + fs/ksmbd/smb2pdu.c | 22 +++++++++++++++++----- + 3 files changed, 23 insertions(+), 5 deletions(-) + +diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c +index 4a4b2b03ff33..b931a99ab9c8 100644 +--- a/fs/ksmbd/asn1.c ++++ b/fs/ksmbd/asn1.c +@@ -214,10 +214,15 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen, + { + struct ksmbd_conn *conn = context; + ++ if (!vlen) ++ return -EINVAL; ++ + conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL); + if (!conn->mechToken) + return -ENOMEM; + ++ conn->mechTokenLen = (unsigned int)vlen; ++ + return 0; + } + +diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h +index 3c005246a32e..342f935f5770 100644 +--- a/fs/ksmbd/connection.h ++++ b/fs/ksmbd/connection.h +@@ -88,6 +88,7 @@ struct ksmbd_conn { + __u16 dialect; + + char *mechToken; ++ unsigned int mechTokenLen; + + struct ksmbd_conn_ops *conn_ops; + +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index bf3bb37c00a9..92ea42876e75 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1414,7 +1414,10 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn, + char *name; + unsigned int name_off, name_len, secbuf_len; + +- secbuf_len = le16_to_cpu(req->SecurityBufferLength); ++ if (conn->use_spnego && conn->mechToken) ++ secbuf_len = conn->mechTokenLen; ++ else ++ secbuf_len = le16_to_cpu(req->SecurityBufferLength); + if (secbuf_len < sizeof(struct authenticate_message)) { + ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len); + return NULL; +@@ -1505,7 +1508,10 @@ static int ntlm_authenticate(struct ksmbd_work *work, + struct authenticate_message *authblob; + + authblob = user_authblob(conn, req); +- sz = le16_to_cpu(req->SecurityBufferLength); ++ if (conn->use_spnego && conn->mechToken) ++ sz = conn->mechTokenLen; ++ else ++ sz = le16_to_cpu(req->SecurityBufferLength); + rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess); + if (rc) { + set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD); +@@ -1778,8 +1784,7 @@ int smb2_sess_setup(struct ksmbd_work *work) + + negblob_off = le16_to_cpu(req->SecurityBufferOffset); + negblob_len = le16_to_cpu(req->SecurityBufferLength); +- if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) || +- negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { ++ if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer)) { + rc = -EINVAL; + goto out_err; + } +@@ -1788,8 +1793,15 @@ int smb2_sess_setup(struct ksmbd_work *work) + negblob_off); + + if (decode_negotiation_token(conn, negblob, negblob_len) == 0) { +- if (conn->mechToken) ++ if (conn->mechToken) { + negblob = (struct negotiate_message *)conn->mechToken; ++ negblob_len = conn->mechTokenLen; ++ } ++ } ++ ++ if (negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { ++ rc = -EINVAL; ++ goto out_err; + } + + if (server_conf.auth_mechs & conn->auth_mechs) { +-- +2.43.0 + diff --git a/queue-5.15/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch b/queue-5.15/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch new file mode 100644 index 00000000000..71b69edb4e0 --- /dev/null +++ b/queue-5.15/scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch @@ -0,0 +1,48 @@ +From 1a712f8328fa90b06511c7f472f97d7f86cd9d5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Dec 2023 14:52:15 -0800 +Subject: scsi: ufs: core: Remove the ufshcd_hba_exit() call from + ufshcd_async_scan() + +From: Bart Van Assche + +[ Upstream commit ee36710912b2075c417100a8acc642c9c6496501 ] + +Calling ufshcd_hba_exit() from a function that is called asynchronously +from ufshcd_init() is wrong because this triggers multiple race +conditions. Instead of calling ufshcd_hba_exit(), log an error message. + +Reported-by: Daniel Mentz +Fixes: 1d337ec2f35e ("ufs: improve init sequence") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20231218225229.2542156-3-bvanassche@acm.org +Reviewed-by: Can Guo +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/ufs/ufshcd.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index 0354e3bce455..03b33c34f702 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -8020,12 +8020,9 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie) + + out: + pm_runtime_put_sync(hba->dev); +- /* +- * If we failed to initialize the device or the device is not +- * present, turn off the power/clocks etc. +- */ ++ + if (ret) +- ufshcd_hba_exit(hba); ++ dev_err(hba->dev, "%s failed: %d\n", __func__, ret); + } + + static const struct attribute_group *ufshcd_driver_groups[] = { +-- +2.43.0 + diff --git a/queue-5.15/scsi-ufs-core-simplify-power-management-during-async.patch b/queue-5.15/scsi-ufs-core-simplify-power-management-during-async.patch new file mode 100644 index 00000000000..3b7b5bac7e2 --- /dev/null +++ b/queue-5.15/scsi-ufs-core-simplify-power-management-during-async.patch @@ -0,0 +1,60 @@ +From 357e1608ab410b1e9ac768c84b6460cb3d2b916a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Dec 2023 14:52:14 -0800 +Subject: scsi: ufs: core: Simplify power management during async scan + +From: Bart Van Assche + +[ Upstream commit daf7795406bf307997366f694888bd317ae5b5fa ] + +ufshcd_init() calls pm_runtime_get_sync() before it calls +async_schedule(). ufshcd_async_scan() calls pm_runtime_put_sync() directly +or indirectly from ufshcd_add_lus(). Simplify ufshcd_async_scan() by always +calling pm_runtime_put_sync() from ufshcd_async_scan(). + +Cc: +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20231218225229.2542156-2-bvanassche@acm.org +Reviewed-by: Can Guo +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Martin K. Petersen +Stable-dep-of: ee36710912b2 ("scsi: ufs: core: Remove the ufshcd_hba_exit() call from ufshcd_async_scan()") +Signed-off-by: Sasha Levin +--- + drivers/scsi/ufs/ufshcd.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index e78461f66400..0354e3bce455 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -7896,7 +7896,6 @@ static int ufshcd_add_lus(struct ufs_hba *hba) + ufs_bsg_probe(hba); + ufshpb_init(hba); + scsi_scan_host(hba->host); +- pm_runtime_put_sync(hba->dev); + + out: + return ret; +@@ -8018,15 +8017,15 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie) + + /* Probe and add UFS logical units */ + ret = ufshcd_add_lus(hba); ++ + out: ++ pm_runtime_put_sync(hba->dev); + /* + * If we failed to initialize the device or the device is not + * present, turn off the power/clocks etc. + */ +- if (ret) { +- pm_runtime_put_sync(hba->dev); ++ if (ret) + ufshcd_hba_exit(hba); +- } + } + + static const struct attribute_group *ufshcd_driver_groups[] = { +-- +2.43.0 + diff --git a/queue-5.15/series b/queue-5.15/series new file mode 100644 index 00000000000..5f3ee59ae17 --- /dev/null +++ b/queue-5.15/series @@ -0,0 +1,11 @@ +ksmbd-free-ppace-array-on-error-in-parse_dacl.patch +ksmbd-don-t-allow-o_trunc-open-on-read-only-share.patch +ksmbd-validate-mech-token-in-session-setup.patch +ksmbd-fix-uaf-issue-in-ksmbd_tcp_new_connection.patch +ksmbd-only-v2-leases-handle-the-directory.patch +iio-adc-ad7091r-set-alert-bit-in-config-register.patch +iio-adc-ad7091r-allow-users-to-configure-device-even.patch +iio-adc-ad7091r-enable-internal-vref-if-external-vre.patch +dmaengine-fix-null-pointer-in-channel-unregistration.patch +scsi-ufs-core-simplify-power-management-during-async.patch +scsi-ufs-core-remove-the-ufshcd_hba_exit-call-from-u.patch -- 2.47.3