From 1d178e12ed660de95636f0612d91572564233f48 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 11 Dec 2023 13:11:22 -0500 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...ilability-of-dedup-breaking-generic-.patch | 56 +++++ ...dump-send-uevent-once-devcd-is-ready.patch | 59 +++++ ...devcoredump-serialize-devcd_del-work.patch | 208 ++++++++++++++++++ queue-5.15/series | 4 + ...otential-null-deref-in-parse_dfs_ref.patch | 43 ++++ 5 files changed, 370 insertions(+) create mode 100644 queue-5.15/cifs-fix-non-availability-of-dedup-breaking-generic-.patch create mode 100644 queue-5.15/devcoredump-send-uevent-once-devcd-is-ready.patch create mode 100644 queue-5.15/devcoredump-serialize-devcd_del-work.patch create mode 100644 queue-5.15/smb-client-fix-potential-null-deref-in-parse_dfs_ref.patch diff --git a/queue-5.15/cifs-fix-non-availability-of-dedup-breaking-generic-.patch b/queue-5.15/cifs-fix-non-availability-of-dedup-breaking-generic-.patch new file mode 100644 index 00000000000..ae864162b7c --- /dev/null +++ b/queue-5.15/cifs-fix-non-availability-of-dedup-breaking-generic-.patch @@ -0,0 +1,56 @@ +From a34315e8c03491d93e66bd4e9138a5eb12ba857a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 14:01:59 +0000 +Subject: cifs: Fix non-availability of dedup breaking generic/304 + +From: David Howells + +[ Upstream commit 691a41d8da4b34fe72f09393505f55f28a8f34ec ] + +Deduplication isn't supported on cifs, but cifs doesn't reject it, instead +treating it as extent duplication/cloning. This can cause generic/304 to go +silly and run for hours on end. + +Fix cifs to indicate EOPNOTSUPP if REMAP_FILE_DEDUP is set in +->remap_file_range(). + +Note that it's unclear whether or not commit b073a08016a1 is meant to cause +cifs to return an error if REMAP_FILE_DEDUP. + +Fixes: b073a08016a1 ("cifs: fix that return -EINVAL when do dedupe operation") +Cc: stable@vger.kernel.org +Suggested-by: Dave Chinner +cc: Xiaoli Feng +cc: Shyam Prasad N +cc: Rohith Surabattula +cc: Jeff Layton +cc: Darrick Wong +cc: fstests@vger.kernel.org +cc: linux-cifs@vger.kernel.org +cc: linux-fsdevel@vger.kernel.org +Link: https://lore.kernel.org/r/3876191.1701555260@warthog.procyon.org.uk/ +Signed-off-by: David Howells +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/cifsfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c +index af688e39f31ac..9bbead15a0287 100644 +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -1144,7 +1144,9 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, + unsigned int xid; + int rc; + +- if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) ++ if (remap_flags & REMAP_FILE_DEDUP) ++ return -EOPNOTSUPP; ++ if (remap_flags & ~REMAP_FILE_ADVISORY) + return -EINVAL; + + cifs_dbg(FYI, "clone range\n"); +-- +2.42.0 + diff --git a/queue-5.15/devcoredump-send-uevent-once-devcd-is-ready.patch b/queue-5.15/devcoredump-send-uevent-once-devcd-is-ready.patch new file mode 100644 index 00000000000..df49a08e354 --- /dev/null +++ b/queue-5.15/devcoredump-send-uevent-once-devcd-is-ready.patch @@ -0,0 +1,59 @@ +From e28b969f6e88a2541bdff980382df9ba84325a97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Nov 2023 20:19:32 +0530 +Subject: devcoredump: Send uevent once devcd is ready + +From: Mukesh Ojha + +[ Upstream commit af54d778a03853801d681c98c0c2a6c316ef9ca7 ] + +dev_coredumpm() creates a devcoredump device and adds it +to the core kernel framework which eventually end up +sending uevent to the user space and later creates a +symbolic link to the failed device. An application +running in userspace may be interested in this symbolic +link to get the name of the failed device. + +In a issue scenario, once uevent sent to the user space +it start reading '/sys/class/devcoredump/devcdX/failing_device' +to get the actual name of the device which might not been +created and it is in its path of creation. + +To fix this, suppress sending uevent till the failing device +symbolic link gets created and send uevent once symbolic +link is created successfully. + +Fixes: 833c95456a70 ("device coredump: add new device coredump class") +Signed-off-by: Mukesh Ojha +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/1700232572-25823-1-git-send-email-quic_mojha@quicinc.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/base/devcoredump.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c +index 1c06781f71148..f3bd9f104bd12 100644 +--- a/drivers/base/devcoredump.c ++++ b/drivers/base/devcoredump.c +@@ -363,6 +363,7 @@ void dev_coredumpm(struct device *dev, struct module *owner, + devcd->devcd_dev.class = &devcd_class; + + mutex_lock(&devcd->mutex); ++ dev_set_uevent_suppress(&devcd->devcd_dev, true); + if (device_add(&devcd->devcd_dev)) + goto put_device; + +@@ -377,6 +378,8 @@ void dev_coredumpm(struct device *dev, struct module *owner, + "devcoredump")) + dev_warn(dev, "devcoredump create_link failed\n"); + ++ dev_set_uevent_suppress(&devcd->devcd_dev, false); ++ kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD); + INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); + schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT); + mutex_unlock(&devcd->mutex); +-- +2.42.0 + diff --git a/queue-5.15/devcoredump-serialize-devcd_del-work.patch b/queue-5.15/devcoredump-serialize-devcd_del-work.patch new file mode 100644 index 00000000000..c5f3315563a --- /dev/null +++ b/queue-5.15/devcoredump-serialize-devcd_del-work.patch @@ -0,0 +1,208 @@ +From 7ee0e7dc6b38e7aee51a5a007646c12985aa1b51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 18:20:24 +0530 +Subject: devcoredump : Serialize devcd_del work + +From: Mukesh Ojha + +[ Upstream commit 01daccf748323dfc61112f474cf2ba81015446b0 ] + +In following scenario(diagram), when one thread X running dev_coredumpm() +adds devcd device to the framework which sends uevent notification to +userspace and another thread Y reads this uevent and call to +devcd_data_write() which eventually try to delete the queued timer that +is not initialized/queued yet. + +So, debug object reports some warning and in the meantime, timer is +initialized and queued from X path. and from Y path, it gets reinitialized +again and timer->entry.pprev=NULL and try_to_grab_pending() stucks. + +To fix this, introduce mutex and a boolean flag to serialize the behaviour. + + cpu0(X) cpu1(Y) + + dev_coredump() uevent sent to user space + device_add() ======================> user space process Y reads the + uevents writes to devcd fd + which results into writes to + + devcd_data_write() + mod_delayed_work() + try_to_grab_pending() + del_timer() + debug_assert_init() + INIT_DELAYED_WORK() + schedule_delayed_work() + debug_object_fixup() + timer_fixup_assert_init() + timer_setup() + do_init_timer() + /* + Above call reinitializes + the timer to + timer->entry.pprev=NULL + and this will be checked + later in timer_pending() call. + */ + timer_pending() + !hlist_unhashed_lockless(&timer->entry) + !h->pprev + /* + del_timer() checks h->pprev and finds + it to be NULL due to which + try_to_grab_pending() stucks. + */ + +Link: https://lore.kernel.org/lkml/2e1f81e2-428c-f11f-ce92-eb11048cb271@quicinc.com/ +Signed-off-by: Mukesh Ojha +Link: https://lore.kernel.org/r/1663073424-13663-1-git-send-email-quic_mojha@quicinc.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: af54d778a038 ("devcoredump: Send uevent once devcd is ready") +Signed-off-by: Sasha Levin +--- + drivers/base/devcoredump.c | 83 +++++++++++++++++++++++++++++++++++++- + 1 file changed, 81 insertions(+), 2 deletions(-) + +diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c +index f4d794d6bb859..1c06781f71148 100644 +--- a/drivers/base/devcoredump.c ++++ b/drivers/base/devcoredump.c +@@ -25,6 +25,47 @@ struct devcd_entry { + struct device devcd_dev; + void *data; + size_t datalen; ++ /* ++ * Here, mutex is required to serialize the calls to del_wk work between ++ * user/kernel space which happens when devcd is added with device_add() ++ * and that sends uevent to user space. User space reads the uevents, ++ * and calls to devcd_data_write() which try to modify the work which is ++ * not even initialized/queued from devcoredump. ++ * ++ * ++ * ++ * cpu0(X) cpu1(Y) ++ * ++ * dev_coredump() uevent sent to user space ++ * device_add() ======================> user space process Y reads the ++ * uevents writes to devcd fd ++ * which results into writes to ++ * ++ * devcd_data_write() ++ * mod_delayed_work() ++ * try_to_grab_pending() ++ * del_timer() ++ * debug_assert_init() ++ * INIT_DELAYED_WORK() ++ * schedule_delayed_work() ++ * ++ * ++ * Also, mutex alone would not be enough to avoid scheduling of ++ * del_wk work after it get flush from a call to devcd_free() ++ * mentioned as below. ++ * ++ * disabled_store() ++ * devcd_free() ++ * mutex_lock() devcd_data_write() ++ * flush_delayed_work() ++ * mutex_unlock() ++ * mutex_lock() ++ * mod_delayed_work() ++ * mutex_unlock() ++ * So, delete_work flag is required. ++ */ ++ struct mutex mutex; ++ bool delete_work; + struct module *owner; + ssize_t (*read)(char *buffer, loff_t offset, size_t count, + void *data, size_t datalen); +@@ -84,7 +125,12 @@ static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj, + struct device *dev = kobj_to_dev(kobj); + struct devcd_entry *devcd = dev_to_devcd(dev); + +- mod_delayed_work(system_wq, &devcd->del_wk, 0); ++ mutex_lock(&devcd->mutex); ++ if (!devcd->delete_work) { ++ devcd->delete_work = true; ++ mod_delayed_work(system_wq, &devcd->del_wk, 0); ++ } ++ mutex_unlock(&devcd->mutex); + + return count; + } +@@ -112,7 +158,12 @@ static int devcd_free(struct device *dev, void *data) + { + struct devcd_entry *devcd = dev_to_devcd(dev); + ++ mutex_lock(&devcd->mutex); ++ if (!devcd->delete_work) ++ devcd->delete_work = true; ++ + flush_delayed_work(&devcd->del_wk); ++ mutex_unlock(&devcd->mutex); + return 0; + } + +@@ -122,6 +173,30 @@ static ssize_t disabled_show(struct class *class, struct class_attribute *attr, + return sysfs_emit(buf, "%d\n", devcd_disabled); + } + ++/* ++ * ++ * disabled_store() worker() ++ * class_for_each_device(&devcd_class, ++ * NULL, NULL, devcd_free) ++ * ... ++ * ... ++ * while ((dev = class_dev_iter_next(&iter)) ++ * devcd_del() ++ * device_del() ++ * put_device() <- last reference ++ * error = fn(dev, data) devcd_dev_release() ++ * devcd_free(dev, data) kfree(devcd) ++ * mutex_lock(&devcd->mutex); ++ * ++ * ++ * In the above diagram, It looks like disabled_store() would be racing with parallely ++ * running devcd_del() and result in memory abort while acquiring devcd->mutex which ++ * is called after kfree of devcd memory after dropping its last reference with ++ * put_device(). However, this will not happens as fn(dev, data) runs ++ * with its own reference to device via klist_node so it is not its last reference. ++ * so, above situation would not occur. ++ */ ++ + static ssize_t disabled_store(struct class *class, struct class_attribute *attr, + const char *buf, size_t count) + { +@@ -278,13 +353,16 @@ void dev_coredumpm(struct device *dev, struct module *owner, + devcd->read = read; + devcd->free = free; + devcd->failing_dev = get_device(dev); ++ devcd->delete_work = false; + ++ mutex_init(&devcd->mutex); + device_initialize(&devcd->devcd_dev); + + dev_set_name(&devcd->devcd_dev, "devcd%d", + atomic_inc_return(&devcd_count)); + devcd->devcd_dev.class = &devcd_class; + ++ mutex_lock(&devcd->mutex); + if (device_add(&devcd->devcd_dev)) + goto put_device; + +@@ -301,10 +379,11 @@ void dev_coredumpm(struct device *dev, struct module *owner, + + INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); + schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT); +- ++ mutex_unlock(&devcd->mutex); + return; + put_device: + put_device(&devcd->devcd_dev); ++ mutex_unlock(&devcd->mutex); + put_module: + module_put(owner); + free: +-- +2.42.0 + diff --git a/queue-5.15/series b/queue-5.15/series index c770f5ddc1c..a3d8bb4f60f 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -135,3 +135,7 @@ kvm-svm-update-efer-software-model-on-cr0-trap-for-sev-es.patch mips-loongson64-reserve-vgabios-memory-on-boot.patch mips-loongson64-enable-dma-noncoherent-support.patch revert-btrfs-add-dmesg-output-for-first-mount-and-last-unmount-of-a-filesystem.patch +cifs-fix-non-availability-of-dedup-breaking-generic-.patch +smb-client-fix-potential-null-deref-in-parse_dfs_ref.patch +devcoredump-serialize-devcd_del-work.patch +devcoredump-send-uevent-once-devcd-is-ready.patch diff --git a/queue-5.15/smb-client-fix-potential-null-deref-in-parse_dfs_ref.patch b/queue-5.15/smb-client-fix-potential-null-deref-in-parse_dfs_ref.patch new file mode 100644 index 00000000000..e1f7a5a5f9a --- /dev/null +++ b/queue-5.15/smb-client-fix-potential-null-deref-in-parse_dfs_ref.patch @@ -0,0 +1,43 @@ +From 9430fe3d043ff8df420657ea1904a29f60d09bb7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 21:49:29 -0300 +Subject: smb: client: fix potential NULL deref in parse_dfs_referrals() + +From: Paulo Alcantara + +[ Upstream commit 92414333eb375ed64f4ae92d34d579e826936480 ] + +If server returned no data for FSCTL_DFS_GET_REFERRALS, @dfs_rsp will +remain NULL and then parse_dfs_referrals() will dereference it. + +Fix this by returning -EIO when no output data is returned. + +Besides, we can't fix it in SMB2_ioctl() as some FSCTLs are allowed to +return no data as per MS-SMB2 2.2.32. + +Fixes: 9d49640a21bf ("CIFS: implement get_dfs_refer for SMB2+") +Cc: stable@vger.kernel.org +Reported-by: Robert Morris +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/smb2ops.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index d8ce079ba9091..7c2ecbb17f542 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -2926,6 +2926,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, + usleep_range(512, 2048); + } while (++retry_count < 5); + ++ if (!rc && !dfs_rsp) ++ rc = -EIO; + if (rc) { + if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP) + cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc); +-- +2.42.0 + -- 2.47.3