]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Wed, 27 Nov 2024 18:04:20 +0000 (13:04 -0500)
committerSasha Levin <sashal@kernel.org>
Wed, 27 Nov 2024 18:04:20 +0000 (13:04 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
12 files changed:
queue-6.1/bluetooth-hci_sync-add-helper-functions-to-manipulat.patch [new file with mode: 0644]
queue-6.1/bluetooth-mgmt-fix-possible-crash-on-mgmt_index_remo.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-add-null-check-for-function-pointer-.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-check-null-initialized-variables.patch [new file with mode: 0644]
queue-6.1/drm-amd-display-initialize-denominators-default-to-1.patch [new file with mode: 0644]
queue-6.1/fbdev-efifb-register-sysfs-groups-through-driver-cor.patch [new file with mode: 0644]
queue-6.1/fpga-bridge-add-owner-module-and-take-its-refcount.patch [new file with mode: 0644]
queue-6.1/fpga-manager-add-owner-module-and-take-its-refcount.patch [new file with mode: 0644]
queue-6.1/fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch [new file with mode: 0644]
queue-6.1/mptcp-fix-possible-integer-overflow-in-mptcp_reset_t.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch [new file with mode: 0644]

diff --git a/queue-6.1/bluetooth-hci_sync-add-helper-functions-to-manipulat.patch b/queue-6.1/bluetooth-hci_sync-add-helper-functions-to-manipulat.patch
new file mode 100644 (file)
index 0000000..76bdcab
--- /dev/null
@@ -0,0 +1,211 @@
+From ed0ffcf4f5cbff66a101156715dfa534496f0bab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 14:25:36 +0800
+Subject: Bluetooth: hci_sync: Add helper functions to manipulate cmd_sync
+ queue
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 505ea2b295929e7be2b4e1bc86ee31cb7862fb01 ]
+
+This adds functions to queue, dequeue and lookup into the cmd_sync
+list.
+
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci_sync.h |  12 +++
+ net/bluetooth/hci_sync.c         | 132 +++++++++++++++++++++++++++++--
+ 2 files changed, 136 insertions(+), 8 deletions(-)
+
+diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
+index 7accd5ff0760b..3a7658d660224 100644
+--- a/include/net/bluetooth/hci_sync.h
++++ b/include/net/bluetooth/hci_sync.h
+@@ -47,6 +47,18 @@ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
+                       void *data, hci_cmd_sync_work_destroy_t destroy);
+ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
+                      void *data, hci_cmd_sync_work_destroy_t destroy);
++struct hci_cmd_sync_work_entry *
++hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++                        void *data, hci_cmd_sync_work_destroy_t destroy);
++int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++                          void *data, hci_cmd_sync_work_destroy_t destroy);
++void hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
++                             struct hci_cmd_sync_work_entry *entry);
++bool hci_cmd_sync_dequeue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++                        void *data, hci_cmd_sync_work_destroy_t destroy);
++bool hci_cmd_sync_dequeue_once(struct hci_dev *hdev,
++                            hci_cmd_sync_work_func_t func, void *data,
++                            hci_cmd_sync_work_destroy_t destroy);
+ int hci_update_eir_sync(struct hci_dev *hdev);
+ int hci_update_class_sync(struct hci_dev *hdev);
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 862ac5e1f4b49..b7a7b2afaa049 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -650,6 +650,17 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
+       INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
+ }
++static void _hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
++                                     struct hci_cmd_sync_work_entry *entry,
++                                     int err)
++{
++      if (entry->destroy)
++              entry->destroy(hdev, entry->data, err);
++
++      list_del(&entry->list);
++      kfree(entry);
++}
++
+ void hci_cmd_sync_clear(struct hci_dev *hdev)
+ {
+       struct hci_cmd_sync_work_entry *entry, *tmp;
+@@ -658,13 +669,8 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
+       cancel_work_sync(&hdev->reenable_adv_work);
+       mutex_lock(&hdev->cmd_sync_work_lock);
+-      list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
+-              if (entry->destroy)
+-                      entry->destroy(hdev, entry->data, -ECANCELED);
+-
+-              list_del(&entry->list);
+-              kfree(entry);
+-      }
++      list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list)
++              _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
+       mutex_unlock(&hdev->cmd_sync_work_lock);
+ }
+@@ -756,6 +762,115 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
+ }
+ EXPORT_SYMBOL(hci_cmd_sync_queue);
++static struct hci_cmd_sync_work_entry *
++_hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++                         void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++      struct hci_cmd_sync_work_entry *entry, *tmp;
++
++      list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
++              if (func && entry->func != func)
++                      continue;
++
++              if (data && entry->data != data)
++                      continue;
++
++              if (destroy && entry->destroy != destroy)
++                      continue;
++
++              return entry;
++      }
++
++      return NULL;
++}
++
++/* Queue HCI command entry once:
++ *
++ * - Lookup if an entry already exist and only if it doesn't creates a new entry
++ *   and queue it.
++ */
++int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++                          void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++      if (hci_cmd_sync_lookup_entry(hdev, func, data, destroy))
++              return 0;
++
++      return hci_cmd_sync_queue(hdev, func, data, destroy);
++}
++EXPORT_SYMBOL(hci_cmd_sync_queue_once);
++
++/* Lookup HCI command entry:
++ *
++ * - Return first entry that matches by function callback or data or
++ *   destroy callback.
++ */
++struct hci_cmd_sync_work_entry *
++hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++                        void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++      struct hci_cmd_sync_work_entry *entry;
++
++      mutex_lock(&hdev->cmd_sync_work_lock);
++      entry = _hci_cmd_sync_lookup_entry(hdev, func, data, destroy);
++      mutex_unlock(&hdev->cmd_sync_work_lock);
++
++      return entry;
++}
++EXPORT_SYMBOL(hci_cmd_sync_lookup_entry);
++
++/* Cancel HCI command entry */
++void hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
++                             struct hci_cmd_sync_work_entry *entry)
++{
++      mutex_lock(&hdev->cmd_sync_work_lock);
++      _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
++      mutex_unlock(&hdev->cmd_sync_work_lock);
++}
++EXPORT_SYMBOL(hci_cmd_sync_cancel_entry);
++
++/* Dequeue one HCI command entry:
++ *
++ * - Lookup and cancel first entry that matches.
++ */
++bool hci_cmd_sync_dequeue_once(struct hci_dev *hdev,
++                             hci_cmd_sync_work_func_t func,
++                             void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++      struct hci_cmd_sync_work_entry *entry;
++
++      entry = hci_cmd_sync_lookup_entry(hdev, func, data, destroy);
++      if (!entry)
++              return false;
++
++      hci_cmd_sync_cancel_entry(hdev, entry);
++
++      return true;
++}
++EXPORT_SYMBOL(hci_cmd_sync_dequeue_once);
++
++/* Dequeue HCI command entry:
++ *
++ * - Lookup and cancel any entry that matches by function callback or data or
++ *   destroy callback.
++ */
++bool hci_cmd_sync_dequeue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++                        void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++      struct hci_cmd_sync_work_entry *entry;
++      bool ret = false;
++
++      mutex_lock(&hdev->cmd_sync_work_lock);
++      while ((entry = _hci_cmd_sync_lookup_entry(hdev, func, data,
++                                                 destroy))) {
++              _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
++              ret = true;
++      }
++      mutex_unlock(&hdev->cmd_sync_work_lock);
++
++      return ret;
++}
++EXPORT_SYMBOL(hci_cmd_sync_dequeue);
++
+ int hci_update_eir_sync(struct hci_dev *hdev)
+ {
+       struct hci_cp_write_eir cp;
+@@ -3023,7 +3138,8 @@ int hci_update_passive_scan(struct hci_dev *hdev)
+           hci_dev_test_flag(hdev, HCI_UNREGISTER))
+               return 0;
+-      return hci_cmd_sync_queue(hdev, update_passive_scan_sync, NULL, NULL);
++      return hci_cmd_sync_queue_once(hdev, update_passive_scan_sync, NULL,
++                                     NULL);
+ }
+ int hci_write_sc_support_sync(struct hci_dev *hdev, u8 val)
+-- 
+2.43.0
+
diff --git a/queue-6.1/bluetooth-mgmt-fix-possible-crash-on-mgmt_index_remo.patch b/queue-6.1/bluetooth-mgmt-fix-possible-crash-on-mgmt_index_remo.patch
new file mode 100644 (file)
index 0000000..fad6c28
--- /dev/null
@@ -0,0 +1,97 @@
+From cf80c87802b865261181061184253e7f3bbb19f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 14:25:37 +0800
+Subject: Bluetooth: MGMT: Fix possible crash on mgmt_index_removed
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit f53e1c9c726d83092167f2226f32bd3b73f26c21 ]
+
+If mgmt_index_removed is called while there are commands queued on
+cmd_sync it could lead to crashes like the bellow trace:
+
+0x0000053D: __list_del_entry_valid_or_report+0x98/0xdc
+0x0000053D: mgmt_pending_remove+0x18/0x58 [bluetooth]
+0x0000053E: mgmt_remove_adv_monitor_complete+0x80/0x108 [bluetooth]
+0x0000053E: hci_cmd_sync_work+0xbc/0x164 [bluetooth]
+
+So while handling mgmt_index_removed this attempts to dequeue
+commands passed as user_data to cmd_sync.
+
+Fixes: 7cf5c2978f23 ("Bluetooth: hci_sync: Refactor remove Adv Monitor")
+Reported-by: jiaymao <quic_jiaymao@quicinc.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+[Xiangyu: BP to fix CVE: CVE-2024-49951, Minor conflict resolution]
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 5a1015ccc0635..82edd9981ab07 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -1457,10 +1457,15 @@ static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
+ static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
+ {
+-      if (cmd->cmd_complete) {
+-              u8 *status = data;
++      struct cmd_lookup *match = data;
++
++      /* dequeue cmd_sync entries using cmd as data as that is about to be
++       * removed/freed.
++       */
++      hci_cmd_sync_dequeue(match->hdev, NULL, cmd, NULL);
+-              cmd->cmd_complete(cmd, *status);
++      if (cmd->cmd_complete) {
++              cmd->cmd_complete(cmd, match->mgmt_status);
+               mgmt_pending_remove(cmd);
+               return;
+@@ -9424,14 +9429,14 @@ void mgmt_index_added(struct hci_dev *hdev)
+ void mgmt_index_removed(struct hci_dev *hdev)
+ {
+       struct mgmt_ev_ext_index ev;
+-      u8 status = MGMT_STATUS_INVALID_INDEX;
++      struct cmd_lookup match = { NULL, hdev, MGMT_STATUS_INVALID_INDEX };
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+               return;
+       switch (hdev->dev_type) {
+       case HCI_PRIMARY:
+-              mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
++              mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
+               if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
+                       mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
+@@ -9489,7 +9494,7 @@ void mgmt_power_on(struct hci_dev *hdev, int err)
+ void __mgmt_power_off(struct hci_dev *hdev)
+ {
+       struct cmd_lookup match = { NULL, hdev };
+-      u8 status, zero_cod[] = { 0, 0, 0 };
++      u8 zero_cod[] = { 0, 0, 0 };
+       mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
+@@ -9501,11 +9506,11 @@ void __mgmt_power_off(struct hci_dev *hdev)
+        * status responses.
+        */
+       if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
+-              status = MGMT_STATUS_INVALID_INDEX;
++              match.mgmt_status = MGMT_STATUS_INVALID_INDEX;
+       else
+-              status = MGMT_STATUS_NOT_POWERED;
++              match.mgmt_status = MGMT_STATUS_NOT_POWERED;
+-      mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
++      mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
+       if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
+               mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-amd-display-add-null-check-for-function-pointer-.patch b/queue-6.1/drm-amd-display-add-null-check-for-function-pointer-.patch
new file mode 100644 (file)
index 0000000..f195627
--- /dev/null
@@ -0,0 +1,54 @@
+From 7c763d769a19b2f029a8c8c8a278e85d91a0775f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 18:10:51 +0800
+Subject: drm/amd/display: Add NULL check for function pointer in
+ dcn32_set_output_transfer_func
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit 28574b08c70e56d34d6f6379326a860b96749051 ]
+
+This commit adds a null check for the set_output_gamma function pointer
+in the dcn32_set_output_transfer_func function. Previously,
+set_output_gamma was being checked for null, but then it was being
+dereferenced without any null check. This could lead to a null pointer
+dereference if set_output_gamma is null.
+
+To fix this, we now ensure that set_output_gamma is not null before
+dereferencing it. We do this by adding a null check for set_output_gamma
+before the call to set_output_gamma.
+
+Cc: Tom Chung <chiahsuan.chung@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Roman Li <roman.li@amd.com>
+Cc: Alex Hung <alex.hung@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+index bd75d3cba0980..d3ad13bf35c85 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+@@ -667,7 +667,9 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
+               }
+       }
+-      mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
++      if (mpc->funcs->set_output_gamma)
++              mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
++
+       return ret;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-amd-display-check-null-initialized-variables.patch b/queue-6.1/drm-amd-display-check-null-initialized-variables.patch
new file mode 100644 (file)
index 0000000..5b6a868
--- /dev/null
@@ -0,0 +1,57 @@
+From 2b6a747ef15334df62fbdacd4896b1cf9eccf2a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 19:23:25 +0800
+Subject: drm/amd/display: Check null-initialized variables
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit 367cd9ceba1933b63bc1d87d967baf6d9fd241d2 ]
+
+[WHAT & HOW]
+drr_timing and subvp_pipe are initialized to null and they are not
+always assigned new values. It is necessary to check for null before
+dereferencing.
+
+This fixes 2 FORWARD_NULL issues reported by Coverity.
+
+Reviewed-by: Nevenko Stupar <nevenko.stupar@amd.com>
+Reviewed-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[Xiangyu: BP to fix CVE: CVE-2024-49898, Minor conflict resolution]
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+index 85e0d1c2a9085..9d8917f72d184 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+@@ -900,8 +900,9 @@ static bool subvp_drr_schedulable(struct dc *dc, struct dc_state *context, struc
+        * for VBLANK: (VACTIVE region of the SubVP pipe can fit the MALL prefetch, VBLANK frame time,
+        * and the max of (VBLANK blanking time, MALL region)).
+        */
+-      if (stretched_drr_us < (1 / (double)drr_timing->min_refresh_in_uhz) * 1000000 * 1000000 &&
+-                      subvp_active_us - prefetch_us - stretched_drr_us - max_vblank_mallregion > 0)
++      if (drr_timing &&
++          stretched_drr_us < (1 / (double)drr_timing->min_refresh_in_uhz) * 1000000 * 1000000 &&
++          subvp_active_us - prefetch_us - stretched_drr_us - max_vblank_mallregion > 0)
+               schedulable = true;
+       return schedulable;
+@@ -966,7 +967,7 @@ static bool subvp_vblank_schedulable(struct dc *dc, struct dc_state *context)
+       if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param) {
+               // SUBVP + DRR case
+               schedulable = subvp_drr_schedulable(dc, context, &context->res_ctx.pipe_ctx[vblank_index]);
+-      } else if (found) {
++      } else if (found && subvp_pipe) {
+               main_timing = &subvp_pipe->stream->timing;
+               phantom_timing = &subvp_pipe->stream->mall_stream_config.paired_stream->timing;
+               vblank_timing = &context->res_ctx.pipe_ctx[vblank_index].stream->timing;
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-amd-display-initialize-denominators-default-to-1.patch b/queue-6.1/drm-amd-display-initialize-denominators-default-to-1.patch
new file mode 100644 (file)
index 0000000..c931c5a
--- /dev/null
@@ -0,0 +1,58 @@
+From 679aac3e7cea9f5dd3457b913b99a46e561bf958 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 17:36:04 +0800
+Subject: drm/amd/display: Initialize denominators' default to 1
+
+From: Alex Hung <alex.hung@amd.com>
+
+[ Upstream commit b995c0a6de6c74656a0c39cd57a0626351b13e3c ]
+
+[WHAT & HOW]
+Variables used as denominators and maybe not assigned to other values,
+should not be 0. Change their default to 1 so they are never 0.
+
+This fixes 10 DIVIDE_BY_ZERO issues reported by Coverity.
+
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Jerry Zuo <jerry.zuo@amd.com>
+Signed-off-by: Alex Hung <alex.hung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[Xiangyu: Bp to fix CVE: CVE-2024-49899
+Discard the dml2_core/dml2_core_shared.c due to this file no exists]
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c   | 2 +-
+ drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c   | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
+index 548cdef8a8ade..543ce9a08cfd3 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
+@@ -78,7 +78,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
+ static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
+ {
+-      unsigned int ret_val = 0;
++      unsigned int ret_val = 1;
+       if (source_format == dm_444_16) {
+               if (!is_chroma)
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
+index 3df559c591f89..70df992f859d7 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
+@@ -39,7 +39,7 @@
+ static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
+ {
+-      unsigned int ret_val = 0;
++      unsigned int ret_val = 1;
+       if (source_format == dm_444_16) {
+               if (!is_chroma)
+-- 
+2.43.0
+
diff --git a/queue-6.1/fbdev-efifb-register-sysfs-groups-through-driver-cor.patch b/queue-6.1/fbdev-efifb-register-sysfs-groups-through-driver-cor.patch
new file mode 100644 (file)
index 0000000..db278ff
--- /dev/null
@@ -0,0 +1,77 @@
+From 88a9a3abde940034e61c4dc272317380d91f2185 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Nov 2024 10:39:00 +0800
+Subject: fbdev: efifb: Register sysfs groups through driver core
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 95cdd538e0e5677efbdf8aade04ec098ab98f457 ]
+
+The driver core can register and cleanup sysfs groups already.
+Make use of that functionality to simplify the error handling and
+cleanup.
+
+Also avoid a UAF race during unregistering where the sysctl attributes
+were usable after the info struct was freed.
+
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/efifb.c | 11 ++---------
+ 1 file changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
+index 16c1aaae9afa4..53944bcc990c5 100644
+--- a/drivers/video/fbdev/efifb.c
++++ b/drivers/video/fbdev/efifb.c
+@@ -570,15 +570,10 @@ static int efifb_probe(struct platform_device *dev)
+               break;
+       }
+-      err = sysfs_create_groups(&dev->dev.kobj, efifb_groups);
+-      if (err) {
+-              pr_err("efifb: cannot add sysfs attrs\n");
+-              goto err_unmap;
+-      }
+       err = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (err < 0) {
+               pr_err("efifb: cannot allocate colormap\n");
+-              goto err_groups;
++              goto err_unmap;
+       }
+       if (efifb_pci_dev)
+@@ -597,8 +592,6 @@ static int efifb_probe(struct platform_device *dev)
+               pm_runtime_put(&efifb_pci_dev->dev);
+       fb_dealloc_cmap(&info->cmap);
+-err_groups:
+-      sysfs_remove_groups(&dev->dev.kobj, efifb_groups);
+ err_unmap:
+       if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC))
+               iounmap(info->screen_base);
+@@ -618,7 +611,6 @@ static int efifb_remove(struct platform_device *pdev)
+       /* efifb_destroy takes care of info cleanup */
+       unregister_framebuffer(info);
+-      sysfs_remove_groups(&pdev->dev.kobj, efifb_groups);
+       return 0;
+ }
+@@ -626,6 +618,7 @@ static int efifb_remove(struct platform_device *pdev)
+ static struct platform_driver efifb_driver = {
+       .driver = {
+               .name = "efi-framebuffer",
++              .dev_groups = efifb_groups,
+       },
+       .probe = efifb_probe,
+       .remove = efifb_remove,
+-- 
+2.43.0
+
diff --git a/queue-6.1/fpga-bridge-add-owner-module-and-take-its-refcount.patch b/queue-6.1/fpga-bridge-add-owner-module-and-take-its-refcount.patch
new file mode 100644 (file)
index 0000000..0be0f4e
--- /dev/null
@@ -0,0 +1,253 @@
+From 14897baa9becf6b5a718188c2681d54ac0bdc535 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 13:38:15 +0800
+Subject: fpga: bridge: add owner module and take its refcount
+
+From: Marco Pagani <marpagan@redhat.com>
+
+[ Upstream commit 1da11f822042eb6ef4b6064dc048f157a7852529 ]
+
+The current implementation of the fpga bridge assumes that the low-level
+module registers a driver for the parent device and uses its owner pointer
+to take the module's refcount. This approach is problematic since it can
+lead to a null pointer dereference while attempting to get the bridge if
+the parent device does not have a driver.
+
+To address this problem, add a module owner pointer to the fpga_bridge
+struct and use it to take the module's refcount. Modify the function for
+registering a bridge to take an additional owner module parameter and
+rename it to avoid conflicts. Use the old function name for a helper macro
+that automatically sets the module that registers the bridge as the owner.
+This ensures compatibility with existing low-level control modules and
+reduces the chances of registering a bridge without setting the owner.
+
+Also, update the documentation to keep it consistent with the new interface
+for registering an fpga bridge.
+
+Other changes: opportunistically move put_device() from __fpga_bridge_get()
+to fpga_bridge_get() and of_fpga_bridge_get() to improve code clarity since
+the bridge device is taken in these functions.
+
+Fixes: 21aeda950c5f ("fpga: add fpga bridge framework")
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Suggested-by: Xu Yilun <yilun.xu@intel.com>
+Reviewed-by: Russ Weight <russ.weight@linux.dev>
+Signed-off-by: Marco Pagani <marpagan@redhat.com>
+Acked-by: Xu Yilun <yilun.xu@intel.com>
+Link: https://lore.kernel.org/r/20240322171839.233864-1-marpagan@redhat.com
+Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-api/fpga/fpga-bridge.rst |  7 ++-
+ drivers/fpga/fpga-bridge.c                    | 57 ++++++++++---------
+ include/linux/fpga/fpga-bridge.h              | 10 +++-
+ 3 files changed, 43 insertions(+), 31 deletions(-)
+
+diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
+index 6042085340953..833f68fb07008 100644
+--- a/Documentation/driver-api/fpga/fpga-bridge.rst
++++ b/Documentation/driver-api/fpga/fpga-bridge.rst
+@@ -6,9 +6,12 @@ API to implement a new FPGA bridge
+ * struct fpga_bridge - The FPGA Bridge structure
+ * struct fpga_bridge_ops - Low level Bridge driver ops
+-* fpga_bridge_register() - Create and register a bridge
++* __fpga_bridge_register() - Create and register a bridge
+ * fpga_bridge_unregister() - Unregister a bridge
++The helper macro ``fpga_bridge_register()`` automatically sets
++the module that registers the FPGA bridge as the owner.
++
+ .. kernel-doc:: include/linux/fpga/fpga-bridge.h
+    :functions: fpga_bridge
+@@ -16,7 +19,7 @@ API to implement a new FPGA bridge
+    :functions: fpga_bridge_ops
+ .. kernel-doc:: drivers/fpga/fpga-bridge.c
+-   :functions: fpga_bridge_register
++   :functions: __fpga_bridge_register
+ .. kernel-doc:: drivers/fpga/fpga-bridge.c
+    :functions: fpga_bridge_unregister
+diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
+index 833ce13ff6f86..698d6cbf782a4 100644
+--- a/drivers/fpga/fpga-bridge.c
++++ b/drivers/fpga/fpga-bridge.c
+@@ -55,33 +55,26 @@ int fpga_bridge_disable(struct fpga_bridge *bridge)
+ }
+ EXPORT_SYMBOL_GPL(fpga_bridge_disable);
+-static struct fpga_bridge *__fpga_bridge_get(struct device *dev,
++static struct fpga_bridge *__fpga_bridge_get(struct device *bridge_dev,
+                                            struct fpga_image_info *info)
+ {
+       struct fpga_bridge *bridge;
+-      int ret = -ENODEV;
+-      bridge = to_fpga_bridge(dev);
++      bridge = to_fpga_bridge(bridge_dev);
+       bridge->info = info;
+-      if (!mutex_trylock(&bridge->mutex)) {
+-              ret = -EBUSY;
+-              goto err_dev;
+-      }
++      if (!mutex_trylock(&bridge->mutex))
++              return ERR_PTR(-EBUSY);
+-      if (!try_module_get(dev->parent->driver->owner))
+-              goto err_ll_mod;
++      if (!try_module_get(bridge->br_ops_owner)) {
++              mutex_unlock(&bridge->mutex);
++              return ERR_PTR(-ENODEV);
++      }
+       dev_dbg(&bridge->dev, "get\n");
+       return bridge;
+-
+-err_ll_mod:
+-      mutex_unlock(&bridge->mutex);
+-err_dev:
+-      put_device(dev);
+-      return ERR_PTR(ret);
+ }
+ /**
+@@ -97,13 +90,18 @@ static struct fpga_bridge *__fpga_bridge_get(struct device *dev,
+ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
+                                      struct fpga_image_info *info)
+ {
+-      struct device *dev;
++      struct fpga_bridge *bridge;
++      struct device *bridge_dev;
+-      dev = class_find_device_by_of_node(fpga_bridge_class, np);
+-      if (!dev)
++      bridge_dev = class_find_device_by_of_node(fpga_bridge_class, np);
++      if (!bridge_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_bridge_get(dev, info);
++      bridge = __fpga_bridge_get(bridge_dev, info);
++      if (IS_ERR(bridge))
++              put_device(bridge_dev);
++
++      return bridge;
+ }
+ EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+@@ -124,6 +122,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data)
+ struct fpga_bridge *fpga_bridge_get(struct device *dev,
+                                   struct fpga_image_info *info)
+ {
++      struct fpga_bridge *bridge;
+       struct device *bridge_dev;
+       bridge_dev = class_find_device(fpga_bridge_class, NULL, dev,
+@@ -131,7 +130,11 @@ struct fpga_bridge *fpga_bridge_get(struct device *dev,
+       if (!bridge_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_bridge_get(bridge_dev, info);
++      bridge = __fpga_bridge_get(bridge_dev, info);
++      if (IS_ERR(bridge))
++              put_device(bridge_dev);
++
++      return bridge;
+ }
+ EXPORT_SYMBOL_GPL(fpga_bridge_get);
+@@ -145,7 +148,7 @@ void fpga_bridge_put(struct fpga_bridge *bridge)
+       dev_dbg(&bridge->dev, "put\n");
+       bridge->info = NULL;
+-      module_put(bridge->dev.parent->driver->owner);
++      module_put(bridge->br_ops_owner);
+       mutex_unlock(&bridge->mutex);
+       put_device(&bridge->dev);
+ }
+@@ -312,18 +315,19 @@ static struct attribute *fpga_bridge_attrs[] = {
+ ATTRIBUTE_GROUPS(fpga_bridge);
+ /**
+- * fpga_bridge_register - create and register an FPGA Bridge device
++ * __fpga_bridge_register - create and register an FPGA Bridge device
+  * @parent:   FPGA bridge device from pdev
+  * @name:     FPGA bridge name
+  * @br_ops:   pointer to structure of fpga bridge ops
+  * @priv:     FPGA bridge private data
++ * @owner:    owner module containing the br_ops
+  *
+  * Return: struct fpga_bridge pointer or ERR_PTR()
+  */
+ struct fpga_bridge *
+-fpga_bridge_register(struct device *parent, const char *name,
+-                   const struct fpga_bridge_ops *br_ops,
+-                   void *priv)
++__fpga_bridge_register(struct device *parent, const char *name,
++                     const struct fpga_bridge_ops *br_ops,
++                     void *priv, struct module *owner)
+ {
+       struct fpga_bridge *bridge;
+       int id, ret;
+@@ -353,6 +357,7 @@ fpga_bridge_register(struct device *parent, const char *name,
+       bridge->name = name;
+       bridge->br_ops = br_ops;
++      bridge->br_ops_owner = owner;
+       bridge->priv = priv;
+       bridge->dev.groups = br_ops->groups;
+@@ -382,7 +387,7 @@ fpga_bridge_register(struct device *parent, const char *name,
+       return ERR_PTR(ret);
+ }
+-EXPORT_SYMBOL_GPL(fpga_bridge_register);
++EXPORT_SYMBOL_GPL(__fpga_bridge_register);
+ /**
+  * fpga_bridge_unregister - unregister an FPGA bridge
+diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h
+index 223da48a6d18b..94c4edd047e54 100644
+--- a/include/linux/fpga/fpga-bridge.h
++++ b/include/linux/fpga/fpga-bridge.h
+@@ -45,6 +45,7 @@ struct fpga_bridge_info {
+  * @dev: FPGA bridge device
+  * @mutex: enforces exclusive reference to bridge
+  * @br_ops: pointer to struct of FPGA bridge ops
++ * @br_ops_owner: module containing the br_ops
+  * @info: fpga image specific information
+  * @node: FPGA bridge list node
+  * @priv: low level driver private date
+@@ -54,6 +55,7 @@ struct fpga_bridge {
+       struct device dev;
+       struct mutex mutex; /* for exclusive reference to bridge */
+       const struct fpga_bridge_ops *br_ops;
++      struct module *br_ops_owner;
+       struct fpga_image_info *info;
+       struct list_head node;
+       void *priv;
+@@ -79,10 +81,12 @@ int of_fpga_bridge_get_to_list(struct device_node *np,
+                              struct fpga_image_info *info,
+                              struct list_head *bridge_list);
++#define fpga_bridge_register(parent, name, br_ops, priv) \
++      __fpga_bridge_register(parent, name, br_ops, priv, THIS_MODULE)
+ struct fpga_bridge *
+-fpga_bridge_register(struct device *parent, const char *name,
+-                   const struct fpga_bridge_ops *br_ops,
+-                   void *priv);
++__fpga_bridge_register(struct device *parent, const char *name,
++                     const struct fpga_bridge_ops *br_ops, void *priv,
++                     struct module *owner);
+ void fpga_bridge_unregister(struct fpga_bridge *br);
+ #endif /* _LINUX_FPGA_BRIDGE_H */
+-- 
+2.43.0
+
diff --git a/queue-6.1/fpga-manager-add-owner-module-and-take-its-refcount.patch b/queue-6.1/fpga-manager-add-owner-module-and-take-its-refcount.patch
new file mode 100644 (file)
index 0000000..a2c4adf
--- /dev/null
@@ -0,0 +1,410 @@
+From 7303f13cb313f1b2defba430f98a392e8b2e5009 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 13:38:16 +0800
+Subject: fpga: manager: add owner module and take its refcount
+
+From: Marco Pagani <marpagan@redhat.com>
+
+[ Upstream commit 4d4d2d4346857bf778fafaa97d6f76bb1663e3c9 ]
+
+The current implementation of the fpga manager assumes that the low-level
+module registers a driver for the parent device and uses its owner pointer
+to take the module's refcount. This approach is problematic since it can
+lead to a null pointer dereference while attempting to get the manager if
+the parent device does not have a driver.
+
+To address this problem, add a module owner pointer to the fpga_manager
+struct and use it to take the module's refcount. Modify the functions for
+registering the manager to take an additional owner module parameter and
+rename them to avoid conflicts. Use the old function names for helper
+macros that automatically set the module that registers the manager as the
+owner. This ensures compatibility with existing low-level control modules
+and reduces the chances of registering a manager without setting the owner.
+
+Also, update the documentation to keep it consistent with the new interface
+for registering an fpga manager.
+
+Other changes: opportunistically move put_device() from __fpga_mgr_get() to
+fpga_mgr_get() and of_fpga_mgr_get() to improve code clarity since the
+manager device is taken in these functions.
+
+Fixes: 654ba4cc0f3e ("fpga manager: ensure lifetime with of_fpga_mgr_get")
+Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Suggested-by: Xu Yilun <yilun.xu@intel.com>
+Signed-off-by: Marco Pagani <marpagan@redhat.com>
+Acked-by: Xu Yilun <yilun.xu@intel.com>
+Link: https://lore.kernel.org/r/20240305192926.84886-1-marpagan@redhat.com
+Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/driver-api/fpga/fpga-mgr.rst | 34 +++++----
+ drivers/fpga/fpga-mgr.c                    | 82 +++++++++++++---------
+ include/linux/fpga/fpga-mgr.h              | 26 +++++--
+ 3 files changed, 89 insertions(+), 53 deletions(-)
+
+diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
+index 49c0a95126532..8d2b79f696c1f 100644
+--- a/Documentation/driver-api/fpga/fpga-mgr.rst
++++ b/Documentation/driver-api/fpga/fpga-mgr.rst
+@@ -24,7 +24,8 @@ How to support a new FPGA device
+ --------------------------------
+ To add another FPGA manager, write a driver that implements a set of ops.  The
+-probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as::
++probe function calls ``fpga_mgr_register()`` or ``fpga_mgr_register_full()``,
++such as::
+       static const struct fpga_manager_ops socfpga_fpga_ops = {
+               .write_init = socfpga_fpga_ops_configure_init,
+@@ -69,10 +70,11 @@ probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as::
+       }
+ Alternatively, the probe function could call one of the resource managed
+-register functions, devm_fpga_mgr_register() or devm_fpga_mgr_register_full().
+-When these functions are used, the parameter syntax is the same, but the call
+-to fpga_mgr_unregister() should be removed. In the above example, the
+-socfpga_fpga_remove() function would not be required.
++register functions, ``devm_fpga_mgr_register()`` or
++``devm_fpga_mgr_register_full()``.  When these functions are used, the
++parameter syntax is the same, but the call to ``fpga_mgr_unregister()`` should be
++removed. In the above example, the ``socfpga_fpga_remove()`` function would not be
++required.
+ The ops will implement whatever device specific register writes are needed to
+ do the programming sequence for this particular FPGA.  These ops return 0 for
+@@ -125,15 +127,19 @@ API for implementing a new FPGA Manager driver
+ * struct fpga_manager -  the FPGA manager struct
+ * struct fpga_manager_ops -  Low level FPGA manager driver ops
+ * struct fpga_manager_info -  Parameter structure for fpga_mgr_register_full()
+-* fpga_mgr_register_full() -  Create and register an FPGA manager using the
++* __fpga_mgr_register_full() -  Create and register an FPGA manager using the
+   fpga_mgr_info structure to provide the full flexibility of options
+-* fpga_mgr_register() -  Create and register an FPGA manager using standard
++* __fpga_mgr_register() -  Create and register an FPGA manager using standard
+   arguments
+-* devm_fpga_mgr_register_full() -  Resource managed version of
+-  fpga_mgr_register_full()
+-* devm_fpga_mgr_register() -  Resource managed version of fpga_mgr_register()
++* __devm_fpga_mgr_register_full() -  Resource managed version of
++  __fpga_mgr_register_full()
++* __devm_fpga_mgr_register() -  Resource managed version of __fpga_mgr_register()
+ * fpga_mgr_unregister() -  Unregister an FPGA manager
++Helper macros ``fpga_mgr_register_full()``, ``fpga_mgr_register()``,
++``devm_fpga_mgr_register_full()``, and ``devm_fpga_mgr_register()`` are available
++to ease the registration.
++
+ .. kernel-doc:: include/linux/fpga/fpga-mgr.h
+    :functions: fpga_mgr_states
+@@ -147,16 +153,16 @@ API for implementing a new FPGA Manager driver
+    :functions: fpga_manager_info
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: fpga_mgr_register_full
++   :functions: __fpga_mgr_register_full
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: fpga_mgr_register
++   :functions: __fpga_mgr_register
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: devm_fpga_mgr_register_full
++   :functions: __devm_fpga_mgr_register_full
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+-   :functions: devm_fpga_mgr_register
++   :functions: __devm_fpga_mgr_register
+ .. kernel-doc:: drivers/fpga/fpga-mgr.c
+    :functions: fpga_mgr_unregister
+diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
+index 8efa67620e216..0c71d91ba7f6e 100644
+--- a/drivers/fpga/fpga-mgr.c
++++ b/drivers/fpga/fpga-mgr.c
+@@ -664,20 +664,16 @@ static struct attribute *fpga_mgr_attrs[] = {
+ };
+ ATTRIBUTE_GROUPS(fpga_mgr);
+-static struct fpga_manager *__fpga_mgr_get(struct device *dev)
++static struct fpga_manager *__fpga_mgr_get(struct device *mgr_dev)
+ {
+       struct fpga_manager *mgr;
+-      mgr = to_fpga_manager(dev);
++      mgr = to_fpga_manager(mgr_dev);
+-      if (!try_module_get(dev->parent->driver->owner))
+-              goto err_dev;
++      if (!try_module_get(mgr->mops_owner))
++              mgr = ERR_PTR(-ENODEV);
+       return mgr;
+-
+-err_dev:
+-      put_device(dev);
+-      return ERR_PTR(-ENODEV);
+ }
+ static int fpga_mgr_dev_match(struct device *dev, const void *data)
+@@ -693,12 +689,18 @@ static int fpga_mgr_dev_match(struct device *dev, const void *data)
+  */
+ struct fpga_manager *fpga_mgr_get(struct device *dev)
+ {
+-      struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev,
+-                                                 fpga_mgr_dev_match);
++      struct fpga_manager *mgr;
++      struct device *mgr_dev;
++
++      mgr_dev = class_find_device(fpga_mgr_class, NULL, dev, fpga_mgr_dev_match);
+       if (!mgr_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_mgr_get(mgr_dev);
++      mgr = __fpga_mgr_get(mgr_dev);
++      if (IS_ERR(mgr))
++              put_device(mgr_dev);
++
++      return mgr;
+ }
+ EXPORT_SYMBOL_GPL(fpga_mgr_get);
+@@ -711,13 +713,18 @@ EXPORT_SYMBOL_GPL(fpga_mgr_get);
+  */
+ struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
+ {
+-      struct device *dev;
++      struct fpga_manager *mgr;
++      struct device *mgr_dev;
+-      dev = class_find_device_by_of_node(fpga_mgr_class, node);
+-      if (!dev)
++      mgr_dev = class_find_device_by_of_node(fpga_mgr_class, node);
++      if (!mgr_dev)
+               return ERR_PTR(-ENODEV);
+-      return __fpga_mgr_get(dev);
++      mgr = __fpga_mgr_get(mgr_dev);
++      if (IS_ERR(mgr))
++              put_device(mgr_dev);
++
++      return mgr;
+ }
+ EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
+@@ -727,7 +734,7 @@ EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
+  */
+ void fpga_mgr_put(struct fpga_manager *mgr)
+ {
+-      module_put(mgr->dev.parent->driver->owner);
++      module_put(mgr->mops_owner);
+       put_device(&mgr->dev);
+ }
+ EXPORT_SYMBOL_GPL(fpga_mgr_put);
+@@ -766,9 +773,10 @@ void fpga_mgr_unlock(struct fpga_manager *mgr)
+ EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
+ /**
+- * fpga_mgr_register_full - create and register an FPGA Manager device
++ * __fpga_mgr_register_full - create and register an FPGA Manager device
+  * @parent:   fpga manager device from pdev
+  * @info:     parameters for fpga manager
++ * @owner:    owner module containing the ops
+  *
+  * The caller of this function is responsible for calling fpga_mgr_unregister().
+  * Using devm_fpga_mgr_register_full() instead is recommended.
+@@ -776,7 +784,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
+  * Return: pointer to struct fpga_manager pointer or ERR_PTR()
+  */
+ struct fpga_manager *
+-fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
++__fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                       struct module *owner)
+ {
+       const struct fpga_manager_ops *mops = info->mops;
+       struct fpga_manager *mgr;
+@@ -804,6 +813,8 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in
+       mutex_init(&mgr->ref_mutex);
++      mgr->mops_owner = owner;
++
+       mgr->name = info->name;
+       mgr->mops = info->mops;
+       mgr->priv = info->priv;
+@@ -841,14 +852,15 @@ fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *in
+       return ERR_PTR(ret);
+ }
+-EXPORT_SYMBOL_GPL(fpga_mgr_register_full);
++EXPORT_SYMBOL_GPL(__fpga_mgr_register_full);
+ /**
+- * fpga_mgr_register - create and register an FPGA Manager device
++ * __fpga_mgr_register - create and register an FPGA Manager device
+  * @parent:   fpga manager device from pdev
+  * @name:     fpga manager name
+  * @mops:     pointer to structure of fpga manager ops
+  * @priv:     fpga manager private data
++ * @owner:    owner module containing the ops
+  *
+  * The caller of this function is responsible for calling fpga_mgr_unregister().
+  * Using devm_fpga_mgr_register() instead is recommended. This simple
+@@ -859,8 +871,8 @@ EXPORT_SYMBOL_GPL(fpga_mgr_register_full);
+  * Return: pointer to struct fpga_manager pointer or ERR_PTR()
+  */
+ struct fpga_manager *
+-fpga_mgr_register(struct device *parent, const char *name,
+-                const struct fpga_manager_ops *mops, void *priv)
++__fpga_mgr_register(struct device *parent, const char *name,
++                  const struct fpga_manager_ops *mops, void *priv, struct module *owner)
+ {
+       struct fpga_manager_info info = { 0 };
+@@ -868,9 +880,9 @@ fpga_mgr_register(struct device *parent, const char *name,
+       info.mops = mops;
+       info.priv = priv;
+-      return fpga_mgr_register_full(parent, &info);
++      return __fpga_mgr_register_full(parent, &info, owner);
+ }
+-EXPORT_SYMBOL_GPL(fpga_mgr_register);
++EXPORT_SYMBOL_GPL(__fpga_mgr_register);
+ /**
+  * fpga_mgr_unregister - unregister an FPGA manager
+@@ -900,9 +912,10 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res)
+ }
+ /**
+- * devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register()
++ * __devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register()
+  * @parent:   fpga manager device from pdev
+  * @info:     parameters for fpga manager
++ * @owner:    owner module containing the ops
+  *
+  * Return:  fpga manager pointer on success, negative error code otherwise.
+  *
+@@ -910,7 +923,8 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res)
+  * function will be called automatically when the managing device is detached.
+  */
+ struct fpga_manager *
+-devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
++__devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                            struct module *owner)
+ {
+       struct fpga_mgr_devres *dr;
+       struct fpga_manager *mgr;
+@@ -919,7 +933,7 @@ devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_inf
+       if (!dr)
+               return ERR_PTR(-ENOMEM);
+-      mgr = fpga_mgr_register_full(parent, info);
++      mgr = __fpga_mgr_register_full(parent, info, owner);
+       if (IS_ERR(mgr)) {
+               devres_free(dr);
+               return mgr;
+@@ -930,14 +944,15 @@ devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_inf
+       return mgr;
+ }
+-EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full);
++EXPORT_SYMBOL_GPL(__devm_fpga_mgr_register_full);
+ /**
+- * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
++ * __devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
+  * @parent:   fpga manager device from pdev
+  * @name:     fpga manager name
+  * @mops:     pointer to structure of fpga manager ops
+  * @priv:     fpga manager private data
++ * @owner:    owner module containing the ops
+  *
+  * Return:  fpga manager pointer on success, negative error code otherwise.
+  *
+@@ -946,8 +961,9 @@ EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full);
+  * device is detached.
+  */
+ struct fpga_manager *
+-devm_fpga_mgr_register(struct device *parent, const char *name,
+-                     const struct fpga_manager_ops *mops, void *priv)
++__devm_fpga_mgr_register(struct device *parent, const char *name,
++                       const struct fpga_manager_ops *mops, void *priv,
++                       struct module *owner)
+ {
+       struct fpga_manager_info info = { 0 };
+@@ -955,9 +971,9 @@ devm_fpga_mgr_register(struct device *parent, const char *name,
+       info.mops = mops;
+       info.priv = priv;
+-      return devm_fpga_mgr_register_full(parent, &info);
++      return __devm_fpga_mgr_register_full(parent, &info, owner);
+ }
+-EXPORT_SYMBOL_GPL(devm_fpga_mgr_register);
++EXPORT_SYMBOL_GPL(__devm_fpga_mgr_register);
+ static void fpga_mgr_dev_release(struct device *dev)
+ {
+diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
+index 54f63459efd6e..0d4fe068f3d8a 100644
+--- a/include/linux/fpga/fpga-mgr.h
++++ b/include/linux/fpga/fpga-mgr.h
+@@ -201,6 +201,7 @@ struct fpga_manager_ops {
+  * @state: state of fpga manager
+  * @compat_id: FPGA manager id for compatibility check.
+  * @mops: pointer to struct of fpga manager ops
++ * @mops_owner: module containing the mops
+  * @priv: low level driver private date
+  */
+ struct fpga_manager {
+@@ -210,6 +211,7 @@ struct fpga_manager {
+       enum fpga_mgr_states state;
+       struct fpga_compat_id *compat_id;
+       const struct fpga_manager_ops *mops;
++      struct module *mops_owner;
+       void *priv;
+ };
+@@ -230,18 +232,30 @@ struct fpga_manager *fpga_mgr_get(struct device *dev);
+ void fpga_mgr_put(struct fpga_manager *mgr);
++#define fpga_mgr_register_full(parent, info) \
++      __fpga_mgr_register_full(parent, info, THIS_MODULE)
+ struct fpga_manager *
+-fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
++__fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                       struct module *owner);
++#define fpga_mgr_register(parent, name, mops, priv) \
++      __fpga_mgr_register(parent, name, mops, priv, THIS_MODULE)
+ struct fpga_manager *
+-fpga_mgr_register(struct device *parent, const char *name,
+-                const struct fpga_manager_ops *mops, void *priv);
++__fpga_mgr_register(struct device *parent, const char *name,
++                  const struct fpga_manager_ops *mops, void *priv, struct module *owner);
++
+ void fpga_mgr_unregister(struct fpga_manager *mgr);
++#define devm_fpga_mgr_register_full(parent, info) \
++      __devm_fpga_mgr_register_full(parent, info, THIS_MODULE)
+ struct fpga_manager *
+-devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
++__devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info,
++                            struct module *owner);
++#define devm_fpga_mgr_register(parent, name, mops, priv) \
++      __devm_fpga_mgr_register(parent, name, mops, priv, THIS_MODULE)
+ struct fpga_manager *
+-devm_fpga_mgr_register(struct device *parent, const char *name,
+-                     const struct fpga_manager_ops *mops, void *priv);
++__devm_fpga_mgr_register(struct device *parent, const char *name,
++                       const struct fpga_manager_ops *mops, void *priv,
++                       struct module *owner);
+ #endif /*_LINUX_FPGA_MGR_H */
+-- 
+2.43.0
+
diff --git a/queue-6.1/fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch b/queue-6.1/fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch
new file mode 100644 (file)
index 0000000..e681f55
--- /dev/null
@@ -0,0 +1,140 @@
+From e54306dd89ec3429bd973d17cc055c3e12c19577 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 16:04:01 +0800
+Subject: fs/inode: Prevent dump_mapping() accessing invalid dentry.d_name.name
+
+From: Li Zhijian <lizhijian@fujitsu.com>
+
+[ Upstream commit 7f7b850689ac06a62befe26e1fd1806799e7f152 ]
+
+It's observed that a crash occurs during hot-remove a memory device,
+in which user is accessing the hugetlb. See calltrace as following:
+
+------------[ cut here ]------------
+WARNING: CPU: 1 PID: 14045 at arch/x86/mm/fault.c:1278 do_user_addr_fault+0x2a0/0x790
+Modules linked in: kmem device_dax cxl_mem cxl_pmem cxl_port cxl_pci dax_hmem dax_pmem nd_pmem cxl_acpi nd_btt cxl_core crc32c_intel nvme virtiofs fuse nvme_core nfit libnvdimm dm_multipath scsi_dh_rdac scsi_dh_emc s
+mirror dm_region_hash dm_log dm_mod
+CPU: 1 PID: 14045 Comm: daxctl Not tainted 6.10.0-rc2-lizhijian+ #492
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
+RIP: 0010:do_user_addr_fault+0x2a0/0x790
+Code: 48 8b 00 a8 04 0f 84 b5 fe ff ff e9 1c ff ff ff 4c 89 e9 4c 89 e2 be 01 00 00 00 bf 02 00 00 00 e8 b5 ef 24 00 e9 42 fe ff ff <0f> 0b 48 83 c4 08 4c 89 ea 48 89 ee 4c 89 e7 5b 5d 41 5c 41 5d 41
+RSP: 0000:ffffc90000a575f0 EFLAGS: 00010046
+RAX: ffff88800c303600 RBX: 0000000000000000 RCX: 0000000000000000
+RDX: 0000000000001000 RSI: ffffffff82504162 RDI: ffffffff824b2c36
+RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000000 R12: ffffc90000a57658
+R13: 0000000000001000 R14: ffff88800bc2e040 R15: 0000000000000000
+FS:  00007f51cb57d880(0000) GS:ffff88807fd00000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000000000001000 CR3: 00000000072e2004 CR4: 00000000001706f0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ <TASK>
+ ? __warn+0x8d/0x190
+ ? do_user_addr_fault+0x2a0/0x790
+ ? report_bug+0x1c3/0x1d0
+ ? handle_bug+0x3c/0x70
+ ? exc_invalid_op+0x14/0x70
+ ? asm_exc_invalid_op+0x16/0x20
+ ? do_user_addr_fault+0x2a0/0x790
+ ? exc_page_fault+0x31/0x200
+ exc_page_fault+0x68/0x200
+<...snip...>
+BUG: unable to handle page fault for address: 0000000000001000
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 800000000ad92067 P4D 800000000ad92067 PUD 7677067 PMD 0
+ Oops: Oops: 0000 [#1] PREEMPT SMP PTI
+ ---[ end trace 0000000000000000 ]---
+ BUG: unable to handle page fault for address: 0000000000001000
+ #PF: supervisor read access in kernel mode
+ #PF: error_code(0x0000) - not-present page
+ PGD 800000000ad92067 P4D 800000000ad92067 PUD 7677067 PMD 0
+ Oops: Oops: 0000 [#1] PREEMPT SMP PTI
+ CPU: 1 PID: 14045 Comm: daxctl Kdump: loaded Tainted: G        W          6.10.0-rc2-lizhijian+ #492
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014
+ RIP: 0010:dentry_name+0x1f4/0x440
+<...snip...>
+? dentry_name+0x2fa/0x440
+vsnprintf+0x1f3/0x4f0
+vprintk_store+0x23a/0x540
+vprintk_emit+0x6d/0x330
+_printk+0x58/0x80
+dump_mapping+0x10b/0x1a0
+? __pfx_free_object_rcu+0x10/0x10
+__dump_page+0x26b/0x3e0
+? vprintk_emit+0xe0/0x330
+? _printk+0x58/0x80
+? dump_page+0x17/0x50
+dump_page+0x17/0x50
+do_migrate_range+0x2f7/0x7f0
+? do_migrate_range+0x42/0x7f0
+? offline_pages+0x2f4/0x8c0
+offline_pages+0x60a/0x8c0
+memory_subsys_offline+0x9f/0x1c0
+? lockdep_hardirqs_on+0x77/0x100
+? _raw_spin_unlock_irqrestore+0x38/0x60
+device_offline+0xe3/0x110
+state_store+0x6e/0xc0
+kernfs_fop_write_iter+0x143/0x200
+vfs_write+0x39f/0x560
+ksys_write+0x65/0xf0
+do_syscall_64+0x62/0x130
+
+Previously, some sanity check have been done in dump_mapping() before
+the print facility parsing '%pd' though, it's still possible to run into
+an invalid dentry.d_name.name.
+
+Since dump_mapping() only needs to dump the filename only, retrieve it
+by itself in a safer way to prevent an unnecessary crash.
+
+Note that either retrieving the filename with '%pd' or
+strncpy_from_kernel_nofault(), the filename could be unreliable.
+
+Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
+Link: https://lore.kernel.org/r/20240826055503.1522320-1-lizhijian@fujitsu.com
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+[Xiangyu: Bp to fix CVE: CVE-2024-49934, modified strscpy step due to 6.1/6.6 need pass
+the max len to strscpy]
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/inode.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 5dd0f81e9721e..0036d5c68fd41 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -593,6 +593,7 @@ void dump_mapping(const struct address_space *mapping)
+       struct hlist_node *dentry_first;
+       struct dentry *dentry_ptr;
+       struct dentry dentry;
++      char fname[64] = {};
+       unsigned long ino;
+       /*
+@@ -628,11 +629,14 @@ void dump_mapping(const struct address_space *mapping)
+               return;
+       }
++      if (strncpy_from_kernel_nofault(fname, dentry.d_name.name, 63) < 0)
++              strscpy(fname, "<invalid>", 63);
+       /*
+-       * if dentry is corrupted, the %pd handler may still crash,
+-       * but it's unlikely that we reach here with a corrupt mapping
++       * Even if strncpy_from_kernel_nofault() succeeded,
++       * the fname could be unreliable
+        */
+-      pr_warn("aops:%ps ino:%lx dentry name:\"%pd\"\n", a_ops, ino, &dentry);
++      pr_warn("aops:%ps ino:%lx dentry name(?):\"%s\"\n",
++              a_ops, ino, fname);
+ }
+ void clear_inode(struct inode *inode)
+-- 
+2.43.0
+
diff --git a/queue-6.1/mptcp-fix-possible-integer-overflow-in-mptcp_reset_t.patch b/queue-6.1/mptcp-fix-possible-integer-overflow-in-mptcp_reset_t.patch
new file mode 100644 (file)
index 0000000..94b71a9
--- /dev/null
@@ -0,0 +1,46 @@
+From 26051fa21c6024fef118065f2a2f04d0fcc5b468 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 15:05:25 +0100
+Subject: mptcp: fix possible integer overflow in mptcp_reset_tout_timer
+
+From: Dmitry Kandybka <d.kandybka@gmail.com>
+
+commit b169e76ebad22cbd055101ee5aa1a7bed0e66606 upstream.
+
+In 'mptcp_reset_tout_timer', promote 'probe_timestamp' to unsigned long
+to avoid possible integer overflow. Compile tested only.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Signed-off-by: Dmitry Kandybka <d.kandybka@gmail.com>
+Link: https://patch.msgid.link/20241107103657.1560536-1-d.kandybka@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Conflict in this version because commit d866ae9aaa43 ("mptcp: add a
+  new sysctl for make after break timeout") is not in this version, and
+  replaced TCP_TIMEWAIT_LEN in the expression. The fix can still be
+  applied the same way: by forcing a cast to unsigned long for the first
+  item. ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mptcp/protocol.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 1acd4e37a0ea6..370afcac26234 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -2708,8 +2708,8 @@ void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)
+       if (!fail_tout && !inet_csk(sk)->icsk_mtup.probe_timestamp)
+               return;
+-      close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies +
+-                      TCP_TIMEWAIT_LEN;
++      close_timeout = (unsigned long)inet_csk(sk)->icsk_mtup.probe_timestamp -
++                      tcp_jiffies32 + jiffies + TCP_TIMEWAIT_LEN;
+       /* the close timeout takes precedence on the fail one, and here at least one of
+        * them is active
+-- 
+2.43.0
+
index 6587f8c2d55b069d9c1eeff7fd536c19b3a3d226..e3dfe9f8d719a16fc27cbf078a736d75c9e0d1ea 100644 (file)
@@ -31,3 +31,14 @@ net-fix-crash-when-config-small-gso_max_size-gso_ipv.patch
 serial-sc16is7xx-fix-invalid-fifo-access-with-specia.patch
 x86-stackprotector-work-around-strict-clang-tls-symb.patch
 cifs-fix-buffer-overflow-when-parsing-nfs-reparse-po.patch
+fpga-bridge-add-owner-module-and-take-its-refcount.patch
+fpga-manager-add-owner-module-and-take-its-refcount.patch
+drm-amd-display-add-null-check-for-function-pointer-.patch
+drm-amd-display-check-null-initialized-variables.patch
+bluetooth-hci_sync-add-helper-functions-to-manipulat.patch
+bluetooth-mgmt-fix-possible-crash-on-mgmt_index_remo.patch
+fbdev-efifb-register-sysfs-groups-through-driver-cor.patch
+mptcp-fix-possible-integer-overflow-in-mptcp_reset_t.patch
+wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch
+drm-amd-display-initialize-denominators-default-to-1.patch
+fs-inode-prevent-dump_mapping-accessing-invalid-dent.patch
diff --git a/queue-6.1/wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch b/queue-6.1/wifi-rtw89-avoid-to-add-interface-to-list-twice-when.patch
new file mode 100644 (file)
index 0000000..3ab7acc
--- /dev/null
@@ -0,0 +1,126 @@
+From fb201fc522d9f55803df657129b1c537b2412df4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Nov 2024 14:25:49 +0800
+Subject: wifi: rtw89: avoid to add interface to list twice when SER
+
+From: Chih-Kang Chang <gary.chang@realtek.com>
+
+[ Upstream commit 7dd5d2514a8ea58f12096e888b0bd050d7eae20a ]
+
+If SER L2 occurs during the WoWLAN resume flow, the add interface flow
+is triggered by ieee80211_reconfig(). However, due to
+rtw89_wow_resume() return failure, it will cause the add interface flow
+to be executed again, resulting in a double add list and causing a kernel
+panic. Therefore, we have added a check to prevent double adding of the
+list.
+
+list_add double add: new=ffff99d6992e2010, prev=ffff99d6992e2010, next=ffff99d695302628.
+------------[ cut here ]------------
+kernel BUG at lib/list_debug.c:37!
+invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
+CPU: 0 PID: 9 Comm: kworker/0:1 Tainted: G        W  O       6.6.30-02659-gc18865c4dfbd #1 770df2933251a0e3c888ba69d1053a817a6376a7
+Hardware name: HP Grunt/Grunt, BIOS Google_Grunt.11031.169.0 06/24/2021
+Workqueue: events_freezable ieee80211_restart_work [mac80211]
+RIP: 0010:__list_add_valid_or_report+0x5e/0xb0
+Code: c7 74 18 48 39 ce 74 13 b0 01 59 5a 5e 5f 41 58 41 59 41 5a 5d e9 e2 d6 03 00 cc 48 c7 c7 8d 4f 17 83 48 89 c2 e8 02 c0 00 00 <0f> 0b 48 c7 c7 aa 8c 1c 83 e8 f4 bf 00 00 0f 0b 48 c7 c7 c8 bc 12
+RSP: 0018:ffffa91b8007bc50 EFLAGS: 00010246
+RAX: 0000000000000058 RBX: ffff99d6992e0900 RCX: a014d76c70ef3900
+RDX: ffffa91b8007bae8 RSI: 00000000ffffdfff RDI: 0000000000000001
+RBP: ffffa91b8007bc88 R08: 0000000000000000 R09: ffffa91b8007bae0
+R10: 00000000ffffdfff R11: ffffffff83a79800 R12: ffff99d695302060
+R13: ffff99d695300900 R14: ffff99d6992e1be0 R15: ffff99d6992e2010
+FS:  0000000000000000(0000) GS:ffff99d6aac00000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 000078fbdba43480 CR3: 000000010e464000 CR4: 00000000001506f0
+Call Trace:
+ <TASK>
+ ? __die_body+0x1f/0x70
+ ? die+0x3d/0x60
+ ? do_trap+0xa4/0x110
+ ? __list_add_valid_or_report+0x5e/0xb0
+ ? do_error_trap+0x6d/0x90
+ ? __list_add_valid_or_report+0x5e/0xb0
+ ? handle_invalid_op+0x30/0x40
+ ? __list_add_valid_or_report+0x5e/0xb0
+ ? exc_invalid_op+0x3c/0x50
+ ? asm_exc_invalid_op+0x16/0x20
+ ? __list_add_valid_or_report+0x5e/0xb0
+ rtw89_ops_add_interface+0x309/0x310 [rtw89_core 7c32b1ee6854761c0321027c8a58c5160e41f48f]
+ drv_add_interface+0x5c/0x130 [mac80211 83e989e6e616bd5b4b8a2b0a9f9352a2c385a3bc]
+ ieee80211_reconfig+0x241/0x13d0 [mac80211 83e989e6e616bd5b4b8a2b0a9f9352a2c385a3bc]
+ ? finish_wait+0x3e/0x90
+ ? synchronize_rcu_expedited+0x174/0x260
+ ? sync_rcu_exp_done_unlocked+0x50/0x50
+ ? wake_bit_function+0x40/0x40
+ ieee80211_restart_work+0xf0/0x140 [mac80211 83e989e6e616bd5b4b8a2b0a9f9352a2c385a3bc]
+ process_scheduled_works+0x1e5/0x480
+ worker_thread+0xea/0x1e0
+ kthread+0xdb/0x110
+ ? move_linked_works+0x90/0x90
+ ? kthread_associate_blkcg+0xa0/0xa0
+ ret_from_fork+0x3b/0x50
+ ? kthread_associate_blkcg+0xa0/0xa0
+ ret_from_fork_asm+0x11/0x20
+ </TASK>
+Modules linked in: dm_integrity async_xor xor async_tx lz4 lz4_compress zstd zstd_compress zram zsmalloc rfcomm cmac uinput algif_hash algif_skcipher af_alg btusb btrtl iio_trig_hrtimer industrialio_sw_trigger btmtk industrialio_configfs btbcm btintel uvcvideo videobuf2_vmalloc iio_trig_sysfs videobuf2_memops videobuf2_v4l2 videobuf2_common uvc snd_hda_codec_hdmi veth snd_hda_intel snd_intel_dspcfg acpi_als snd_hda_codec industrialio_triggered_buffer kfifo_buf snd_hwdep industrialio i2c_piix4 snd_hda_core designware_i2s ip6table_nat snd_soc_max98357a xt_MASQUERADE xt_cgroup snd_soc_acp_rt5682_mach fuse rtw89_8922ae(O) rtw89_8922a(O) rtw89_pci(O) rtw89_core(O) 8021q mac80211(O) bluetooth ecdh_generic ecc cfg80211 r8152 mii joydev
+gsmi: Log Shutdown Reason 0x03
+---[ end trace 0000000000000000 ]---
+
+Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240731070506.46100-4-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/mac80211.c |  4 +++-
+ drivers/net/wireless/realtek/rtw89/util.h     | 18 ++++++++++++++++++
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
+index 3a108b13aa596..f7880499aeb09 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
+@@ -105,7 +105,9 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
+       mutex_lock(&rtwdev->mutex);
+       rtwvif->rtwdev = rtwdev;
+-      list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
++      if (!rtw89_rtwvif_in_list(rtwdev, rtwvif))
++              list_add_tail(&rtwvif->list, &rtwdev->rtwvifs_list);
++
+       INIT_WORK(&rtwvif->update_beacon_work, rtw89_core_update_beacon_work);
+       rtw89_leave_ps_mode(rtwdev);
+diff --git a/drivers/net/wireless/realtek/rtw89/util.h b/drivers/net/wireless/realtek/rtw89/util.h
+index 1ae80b7561daa..f9f52b5b63b94 100644
+--- a/drivers/net/wireless/realtek/rtw89/util.h
++++ b/drivers/net/wireless/realtek/rtw89/util.h
+@@ -14,6 +14,24 @@
+ #define rtw89_for_each_rtwvif(rtwdev, rtwvif)                                \
+       list_for_each_entry(rtwvif, &(rtwdev)->rtwvifs_list, list)
++/* Before adding rtwvif to list, we need to check if it already exist, beacase
++ * in some case such as SER L2 happen during WoWLAN flow, calling reconfig
++ * twice cause the list to be added twice.
++ */
++static inline bool rtw89_rtwvif_in_list(struct rtw89_dev *rtwdev,
++                                      struct rtw89_vif *new)
++{
++      struct rtw89_vif *rtwvif;
++
++      lockdep_assert_held(&rtwdev->mutex);
++
++      rtw89_for_each_rtwvif(rtwdev, rtwvif)
++              if (rtwvif == new)
++                      return true;
++
++      return false;
++}
++
+ /* The result of negative dividend and positive divisor is undefined, but it
+  * should be one case of round-down or round-up. So, make it round-down if the
+  * result is round-up.
+-- 
+2.43.0
+