]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 May 2026 09:49:03 +0000 (11:49 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 May 2026 09:49:03 +0000 (11:49 +0200)
added patches:
cgroup-cpuset-reset-dl-migration-state-on-can_attach-failure.patch
fs-ntfs3-handle-attr_set_size-errors-when-truncating-files.patch
net-ethtool-fix-null-pointer-dereference-in-phy_reply_size.patch
net-ethtool-phy-avoid-null-deref-when-phy-driver-is-unbound.patch
sched_ext-avoid-uaf-in-scx_root_enable_workfn-init-failure-path.patch
sched_ext-fix-missing-warning-in-scx_set_task_state-default-case.patch
tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch
tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch
tracing-fprobe-remove-unused-local-variable.patch
tracing-fprobe-use-ftrace-if-config_dynamic_ftrace_with_args.patch

queue-6.18/cgroup-cpuset-reset-dl-migration-state-on-can_attach-failure.patch [new file with mode: 0644]
queue-6.18/fs-ntfs3-handle-attr_set_size-errors-when-truncating-files.patch [new file with mode: 0644]
queue-6.18/net-ethtool-fix-null-pointer-dereference-in-phy_reply_size.patch [new file with mode: 0644]
queue-6.18/net-ethtool-phy-avoid-null-deref-when-phy-driver-is-unbound.patch [new file with mode: 0644]
queue-6.18/sched_ext-avoid-uaf-in-scx_root_enable_workfn-init-failure-path.patch [new file with mode: 0644]
queue-6.18/sched_ext-fix-missing-warning-in-scx_set_task_state-default-case.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch [new file with mode: 0644]
queue-6.18/tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch [new file with mode: 0644]
queue-6.18/tracing-fprobe-remove-unused-local-variable.patch [new file with mode: 0644]
queue-6.18/tracing-fprobe-use-ftrace-if-config_dynamic_ftrace_with_args.patch [new file with mode: 0644]

diff --git a/queue-6.18/cgroup-cpuset-reset-dl-migration-state-on-can_attach-failure.patch b/queue-6.18/cgroup-cpuset-reset-dl-migration-state-on-can_attach-failure.patch
new file mode 100644 (file)
index 0000000..a3059ff
--- /dev/null
@@ -0,0 +1,70 @@
+From stable+bounces-253781-greg=kroah.com@vger.kernel.org Fri May 22 15:01:31 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 08:54:20 -0400
+Subject: cgroup/cpuset: Reset DL migration state on can_attach() failure
+To: stable@vger.kernel.org
+Cc: Guopeng Zhang <zhangguopeng@kylinos.cn>, Tejun Heo <tj@kernel.org>, Chen Ridong <chenridong@huaweicloud.com>, Waiman Long <longman@redhat.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260522125420.3841043-1-sashal@kernel.org>
+
+From: Guopeng Zhang <zhangguopeng@kylinos.cn>
+
+[ Upstream commit 4a39eda5fdd867fc39f3c039714dd432cee00268 ]
+
+cpuset_can_attach() accumulates temporary SCHED_DEADLINE migration
+state in the destination cpuset while walking the taskset.
+
+If a later task_can_attach() or security_task_setscheduler() check
+fails, cgroup_migrate_execute() treats cpuset as the failing subsystem
+and does not call cpuset_cancel_attach() for it. The partially
+accumulated state is then left behind and can be consumed by a later
+attach, corrupting cpuset DL task accounting and pending DL bandwidth
+accounting.
+
+Reset the pending DL migration state from the common error exit when
+ret is non-zero. Successful can_attach() keeps the state for
+cpuset_attach() or cpuset_cancel_attach().
+
+Fixes: 2ef269ef1ac0 ("cgroup/cpuset: Free DL BW in case can_attach() fails")
+Cc: stable@vger.kernel.org # v6.10+
+Signed-off-by: Guopeng Zhang <zhangguopeng@kylinos.cn>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reviewed-by: Chen Ridong <chenridong@huaweicloud.com>
+Reviewed-by: Waiman Long <longman@redhat.com>
+[ omitted upstream context line `cs->dl_bw_cpu = cpu;` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/cgroup/cpuset.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -3163,16 +3163,13 @@ static int cpuset_can_attach(struct cgro
+               int cpu = cpumask_any_and(cpu_active_mask, cs->effective_cpus);
+               if (unlikely(cpu >= nr_cpu_ids)) {
+-                      reset_migrate_dl_data(cs);
+                       ret = -EINVAL;
+                       goto out_unlock;
+               }
+               ret = dl_bw_alloc(cpu, cs->sum_migrate_dl_bw);
+-              if (ret) {
+-                      reset_migrate_dl_data(cs);
++              if (ret)
+                       goto out_unlock;
+-              }
+       }
+ out_success:
+@@ -3181,7 +3178,10 @@ out_success:
+        * changes which zero cpus/mems_allowed.
+        */
+       cs->attach_in_progress++;
++
+ out_unlock:
++      if (ret)
++              reset_migrate_dl_data(cs);
+       mutex_unlock(&cpuset_mutex);
+       return ret;
+ }
diff --git a/queue-6.18/fs-ntfs3-handle-attr_set_size-errors-when-truncating-files.patch b/queue-6.18/fs-ntfs3-handle-attr_set_size-errors-when-truncating-files.patch
new file mode 100644 (file)
index 0000000..89e9c21
--- /dev/null
@@ -0,0 +1,69 @@
+From stable+bounces-254710-greg=kroah.com@vger.kernel.org Thu May 28 05:21:19 2026
+From: Bin Lan <lanbincn@139.com>
+Date: Thu, 28 May 2026 11:20:28 +0800
+Subject: fs/ntfs3: handle attr_set_size() errors when truncating files
+To: gregkh@linuxfoundation.org, sashal@kernel.org, stable@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org, Konstantin Komarov <almaz.alexandrovich@paragon-software.com>, Bin Lan <lanbincn@139.com>
+Message-ID: <20260528032028.58379-1-lanbincn@139.com>
+
+From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+
+[ Upstream commit 576248a34b927e93b2fd3fff7df735ba73ad7d01 ]
+
+If attr_set_size() fails while truncating down, the error is silently
+ignored and the inode may be left in an inconsistent state.
+
+Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
+[ Minor context conflict resolved. ]
+Signed-off-by: Bin Lan <lanbincn@139.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ntfs3/file.c |   12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/fs/ntfs3/file.c
++++ b/fs/ntfs3/file.c
+@@ -458,8 +458,8 @@ static int ntfs_truncate(struct inode *i
+ {
+       struct super_block *sb = inode->i_sb;
+       struct ntfs_inode *ni = ntfs_i(inode);
+-      int err, dirty = 0;
+       u64 new_valid;
++      int err;
+       if (!S_ISREG(inode->i_mode))
+               return 0;
+@@ -475,7 +475,6 @@ static int ntfs_truncate(struct inode *i
+       }
+       new_valid = ntfs_up_block(sb, min_t(u64, ni->i_valid, new_size));
+-
+       truncate_setsize(inode, new_size);
+       ni_lock(ni);
+@@ -489,22 +488,19 @@ static int ntfs_truncate(struct inode *i
+               ni->i_valid = new_valid;
+       ni_unlock(ni);
++      if (unlikely(err))
++              return err;
+       ni->std_fa |= FILE_ATTRIBUTE_ARCHIVE;
+       inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
+       if (!IS_DIRSYNC(inode)) {
+-              dirty = 1;
++              mark_inode_dirty(inode);
+       } else {
+               err = ntfs_sync_inode(inode);
+               if (err)
+                       return err;
+       }
+-      if (dirty)
+-              mark_inode_dirty(inode);
+-
+-      /*ntfs_flush_inodes(inode->i_sb, inode, NULL);*/
+-
+       return 0;
+ }
diff --git a/queue-6.18/net-ethtool-fix-null-pointer-dereference-in-phy_reply_size.patch b/queue-6.18/net-ethtool-fix-null-pointer-dereference-in-phy_reply_size.patch
new file mode 100644 (file)
index 0000000..ed4a47f
--- /dev/null
@@ -0,0 +1,106 @@
+From stable+bounces-253784-greg=kroah.com@vger.kernel.org Fri May 22 15:31:39 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 09:02:59 -0400
+Subject: net: ethtool: fix NULL pointer dereference in phy_reply_size
+To: stable@vger.kernel.org
+Cc: Quan Sun <2022090917019@std.uestc.edu.cn>, Maxime Chevallier <maxime.chevallier@bootlin.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260522130300.3869084-1-sashal@kernel.org>
+
+From: Quan Sun <2022090917019@std.uestc.edu.cn>
+
+[ Upstream commit 4908f1395fb1b832ceec11584af649874a2732ea ]
+
+In phy_prepare_data(), several strings such as 'name', 'drvname',
+'upstream_sfp_name', and 'downstream_sfp_name' are allocated using
+kstrdup(). However, these allocations were not checked  for failure.
+
+If kstrdup() fails for 'name', it returns NULL while the function
+continues. This leads to a kernel NULL pointer dereference and panic
+later in phy_reply_size() when it unconditionally calls strlen() on
+the NULL pointer.
+
+While other strings like 'upstream_sfp_name' might be checked before
+access in certain code paths, failing to handle these allocations
+consistently can lead to incomplete data reporting or hidden bugs.
+
+Fix this by adding proper NULL checks for all kstrdup() calls in
+phy_prepare_data() and implement a centralized error handling path
+using goto labels to ensure all previously allocated resources are
+freed on failure.
+
+Fixes: 9dd2ad5e92b9 ("net: ethtool: phy: Convert the PHY_GET command to generic phy dump")
+Signed-off-by: Quan Sun <2022090917019@std.uestc.edu.cn>
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260507131738.1173835-1-2022090917019@std.uestc.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: e3adf69f8eb1 ("net: ethtool: phy: avoid NULL deref when PHY driver is unbound")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ethtool/phy.c |   32 ++++++++++++++++++++++++++++++--
+ 1 file changed, 30 insertions(+), 2 deletions(-)
+
+--- a/net/ethtool/phy.c
++++ b/net/ethtool/phy.c
+@@ -76,6 +76,7 @@ static int phy_prepare_data(const struct
+       struct nlattr **tb = info->attrs;
+       struct phy_device_node *pdn;
+       struct phy_device *phydev;
++      int ret;
+       /* RTNL is held by the caller */
+       phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PHY_HEADER,
+@@ -88,8 +89,17 @@ static int phy_prepare_data(const struct
+               return -EOPNOTSUPP;
+       rep_data->phyindex = phydev->phyindex;
++
+       rep_data->name = kstrdup(dev_name(&phydev->mdio.dev), GFP_KERNEL);
++      if (!rep_data->name)
++              return -ENOMEM;
++
+       rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
++      if (!rep_data->drvname) {
++              ret = -ENOMEM;
++              goto err_free_name;
++      }
++
+       rep_data->upstream_type = pdn->upstream_type;
+       if (pdn->upstream_type == PHY_UPSTREAM_PHY) {
+@@ -97,15 +107,33 @@ static int phy_prepare_data(const struct
+               rep_data->upstream_index = upstream->phyindex;
+       }
+-      if (pdn->parent_sfp_bus)
++      if (pdn->parent_sfp_bus) {
+               rep_data->upstream_sfp_name = kstrdup(sfp_get_name(pdn->parent_sfp_bus),
+                                                     GFP_KERNEL);
++              if (!rep_data->upstream_sfp_name) {
++                      ret = -ENOMEM;
++                      goto err_free_drvname;
++              }
++      }
+-      if (phydev->sfp_bus)
++      if (phydev->sfp_bus) {
+               rep_data->downstream_sfp_name = kstrdup(sfp_get_name(phydev->sfp_bus),
+                                                       GFP_KERNEL);
++              if (!rep_data->downstream_sfp_name) {
++                      ret = -ENOMEM;
++                      goto err_free_upstream_sfp;
++              }
++      }
+       return 0;
++
++err_free_upstream_sfp:
++      kfree(rep_data->upstream_sfp_name);
++err_free_drvname:
++      kfree(rep_data->drvname);
++err_free_name:
++      kfree(rep_data->name);
++      return ret;
+ }
+ static int phy_fill_reply(struct sk_buff *skb,
diff --git a/queue-6.18/net-ethtool-phy-avoid-null-deref-when-phy-driver-is-unbound.patch b/queue-6.18/net-ethtool-phy-avoid-null-deref-when-phy-driver-is-unbound.patch
new file mode 100644 (file)
index 0000000..f06a02f
--- /dev/null
@@ -0,0 +1,59 @@
+From stable+bounces-253785-greg=kroah.com@vger.kernel.org Fri May 22 15:16:54 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 09:03:00 -0400
+Subject: net: ethtool: phy: avoid NULL deref when PHY driver is unbound
+To: stable@vger.kernel.org
+Cc: David Carlier <devnexen@gmail.com>, Maxime Chevallier <maxime.chevallier@bootlin.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260522130300.3869084-2-sashal@kernel.org>
+
+From: David Carlier <devnexen@gmail.com>
+
+[ Upstream commit e3adf69f8eb121a9128c2b0029efd050d3649153 ]
+
+phydev->drv can become NULL while the phy_device is still attached to
+its net_device, namely after the PHY driver is unbound via sysfs:
+
+       echo <mdio_id> > /sys/bus/mdio_bus/drivers/<phy_drv>/unbind
+
+phy_remove() clears phydev->drv but doesn't call phy_detach(), so the
+phy_device stays in the link topology xarray and ethnl_req_get_phydev()
+still hands it back. ETHTOOL_MSG_PHY_GET then oopses on:
+
+       rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+
+drvname is already treated as optional by phy_reply_size(),
+phy_fill_reply() and phy_cleanup_data(), so just skip the allocation
+when there is no driver bound.
+
+Fixes: 9dd2ad5e92b9 ("net: ethtool: phy: Convert the PHY_GET command to generic phy dump")
+Cc: stable@vger.kernel.org # 6.13.x
+Signed-off-by: David Carlier <devnexen@gmail.com>
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260509215046.107157-1-devnexen@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ethtool/phy.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/net/ethtool/phy.c
++++ b/net/ethtool/phy.c
+@@ -94,10 +94,12 @@ static int phy_prepare_data(const struct
+       if (!rep_data->name)
+               return -ENOMEM;
+-      rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
+-      if (!rep_data->drvname) {
+-              ret = -ENOMEM;
+-              goto err_free_name;
++      if (phydev->drv) {
++              rep_data->drvname = kstrdup(phydev->drv->name, GFP_KERNEL);
++              if (!rep_data->drvname) {
++                      ret = -ENOMEM;
++                      goto err_free_name;
++              }
+       }
+       rep_data->upstream_type = pdn->upstream_type;
diff --git a/queue-6.18/sched_ext-avoid-uaf-in-scx_root_enable_workfn-init-failure-path.patch b/queue-6.18/sched_ext-avoid-uaf-in-scx_root_enable_workfn-init-failure-path.patch
new file mode 100644 (file)
index 0000000..cb32046
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-253570-greg=kroah.com@vger.kernel.org Thu May 21 16:31:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:53:58 -0400
+Subject: sched_ext: Avoid UAF in scx_root_enable_workfn() init failure path
+To: stable@vger.kernel.org
+Cc: Tejun Heo <tj@kernel.org>, Sashiko <sashiko-bot@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260521135358.1280483-2-sashal@kernel.org>
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 9a415cc53711f2238e0f0ca8a6bcc796c003b127 ]
+
+In scx_root_enable_workfn(), put_task_struct(p) is called before scx_error()
+dereferences p->comm and p->pid. If the iterator's reference is the last
+drop, the task is freed synchronously and the deref becomes a UAF.
+
+Move put_task_struct() past scx_error().
+
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Closes: https://lore.kernel.org/all/20260511214031.AF5E9C2BCB0@smtp.kernel.org/
+Fixes: f0e1a0643a59 ("sched_ext: Implement BPF extensible scheduler class")
+Cc: stable@vger.kernel.org # v6.12+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+[ kept `scx_init_task()` call site instead of `__scx_init_task()`/`task_rq_lock` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/ext.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -4812,10 +4812,10 @@ static void scx_enable_workfn(struct kth
+               ret = scx_init_task(p, task_group(p), false);
+               if (ret) {
+-                      put_task_struct(p);
+                       scx_task_iter_stop(&sti);
+                       scx_error(sch, "ops.init_task() failed (%d) for %s[%d]",
+                                 ret, p->comm, p->pid);
++                      put_task_struct(p);
+                       goto err_disable_unlock_all;
+               }
diff --git a/queue-6.18/sched_ext-fix-missing-warning-in-scx_set_task_state-default-case.patch b/queue-6.18/sched_ext-fix-missing-warning-in-scx_set_task_state-default-case.patch
new file mode 100644 (file)
index 0000000..ac0a24c
--- /dev/null
@@ -0,0 +1,57 @@
+From stable+bounces-253569-greg=kroah.com@vger.kernel.org Thu May 21 16:59:34 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:53:57 -0400
+Subject: sched_ext: Fix missing warning in scx_set_task_state() default case
+To: stable@vger.kernel.org
+Cc: Samuele Mariotti <smariotti@disroot.org>, Paolo Valente <paolo.valente@unimore.it>, Andrea Righi <arighi@nvidia.com>, Tejun Heo <tj@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260521135358.1280483-1-sashal@kernel.org>
+
+From: Samuele Mariotti <smariotti@disroot.org>
+
+[ Upstream commit b905ee77d5f557a83a485b4146210f54f13365fc ]
+
+In scx_set_task_state(), the default case was setting the
+warn flag, but then returning immediately. This is problematic
+because the only purpose of the warn flag is to trigger
+WARN_ONCE, but the early return prevented it from ever firing,
+leaving invalid task states undetected and untraced.
+
+To fix this, a WARN_ONCE call is now added directly in the
+default case.
+
+The fix addresses two aspects:
+
+ - Guarantees the invalid task states are properly logged
+   and traced.
+
+ - Provides a distinct warning message
+   ("sched_ext: Invalid task state") specifically for
+   states outside the defined scx_task_state enum values,
+   making it easier to distinguish from other transition
+   warnings.
+
+This ensures proper detection and reporting of invalid states.
+
+Signed-off-by: Samuele Mariotti <smariotti@disroot.org>
+Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
+Reviewed-by: Andrea Righi <arighi@nvidia.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Stable-dep-of: 9a415cc53711 ("sched_ext: Avoid UAF in scx_root_enable_workfn() init failure path")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/ext.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -2800,7 +2800,8 @@ static void scx_set_task_state(struct ta
+               warn = prev_state != SCX_TASK_READY;
+               break;
+       default:
+-              warn = true;
++              WARN_ONCE(1, "sched_ext: Invalid task state %d -> %d for %s[%d]",
++                        prev_state, state, p->comm, p->pid);
+               return;
+       }
index a1433e75d227e75821798157bc69465bf462fc36..6b9747503ac8d1d2e03e61c310f871d93d75ae3f 100644 (file)
@@ -66,3 +66,13 @@ netfilter-ip6t_hbh-reject-oversized-option-lists.patch
 netfilter-nf_queue-hold-bridge-skb-dev-while-queued.patch
 netfilter-ipset-stop-hash-range-iteration-at-end.patch
 netfilter-nft_inner-fix-ipv6-inner_thoff-desync.patch
+sched_ext-fix-missing-warning-in-scx_set_task_state-default-case.patch
+sched_ext-avoid-uaf-in-scx_root_enable_workfn-init-failure-path.patch
+tracing-fprobe-remove-unused-local-variable.patch
+tracing-fprobe-use-ftrace-if-config_dynamic_ftrace_with_args.patch
+tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch
+tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch
+cgroup-cpuset-reset-dl-migration-state-on-can_attach-failure.patch
+net-ethtool-fix-null-pointer-dereference-in-phy_reply_size.patch
+net-ethtool-phy-avoid-null-deref-when-phy-driver-is-unbound.patch
+fs-ntfs3-handle-attr_set_size-errors-when-truncating-files.patch
diff --git a/queue-6.18/tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch b/queue-6.18/tracing-fprobe-avoid-kcalloc-in-rcu_read_lock-section.patch
new file mode 100644 (file)
index 0000000..ae5b5a3
--- /dev/null
@@ -0,0 +1,188 @@
+From stable+bounces-253539-greg=kroah.com@vger.kernel.org Thu May 21 15:10:32 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 08:58:12 -0400
+Subject: tracing/fprobe: Avoid kcalloc() in rcu_read_lock section
+To: stable@vger.kernel.org
+Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260521125813.1165339-3-sashal@kernel.org>
+
+From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
+
+[ Upstream commit aa72812b49104bb5a38272fc9541feb62ca6fd32 ]
+
+fprobe_remove_node_in_module() is called under RCU read locked, but
+this invokes kcalloc() if there are more than 8 fprobes installed
+on the module. Sashiko warns it because kcalloc() can sleep [1].
+
+ [1] https://sashiko.dev/#/patchset/177552432201.853249.5125045538812833325.stgit%40mhiramat.tok.corp.google.com
+
+To fix this issue, expand the batch size to 128 and do not expand
+the fprobe_addr_list, but just cancel walking on fprobe_ip_table,
+update fgraph/ftrace_ops and retry the loop again.
+
+Link: https://lore.kernel.org/all/177669367206.132053.1493637946869032744.stgit@mhiramat.tok.corp.google.com/
+
+Fixes: 0de4c70d04a4 ("tracing: fprobe: use rhltable for fprobe_ip_table")
+Cc: stable@vger.kernel.org
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Stable-dep-of: 0ac0058a74ac ("tracing/fprobe: Check the same type fprobe on table as the unregistered one")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/fprobe.c |   92 ++++++++++++++++++++++++--------------------------
+ 1 file changed, 45 insertions(+), 47 deletions(-)
+
+--- a/kernel/trace/fprobe.c
++++ b/kernel/trace/fprobe.c
+@@ -344,11 +344,10 @@ static bool fprobe_is_ftrace(struct fpro
+ }
+ #ifdef CONFIG_MODULES
+-static void fprobe_set_ips(unsigned long *ips, unsigned int cnt, int remove,
+-                         int reset)
++static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt)
+ {
+-      ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, remove, reset);
+-      ftrace_set_filter_ips(&fprobe_ftrace_ops, ips, cnt, remove, reset);
++      ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, 1, 0);
++      ftrace_set_filter_ips(&fprobe_ftrace_ops, ips, cnt, 1, 0);
+ }
+ #endif
+ #else
+@@ -367,10 +366,9 @@ static bool fprobe_is_ftrace(struct fpro
+ }
+ #ifdef CONFIG_MODULES
+-static void fprobe_set_ips(unsigned long *ips, unsigned int cnt, int remove,
+-                         int reset)
++static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt)
+ {
+-      ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, remove, reset);
++      ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, 1, 0);
+ }
+ #endif
+ #endif /* !CONFIG_DYNAMIC_FTRACE_WITH_ARGS && !CONFIG_DYNAMIC_FTRACE_WITH_REGS */
+@@ -543,7 +541,7 @@ static void fprobe_graph_remove_ips(unsi
+ #ifdef CONFIG_MODULES
+-#define FPROBE_IPS_BATCH_INIT 8
++#define FPROBE_IPS_BATCH_INIT 128
+ /* instruction pointer address list */
+ struct fprobe_addr_list {
+       int index;
+@@ -551,45 +549,24 @@ struct fprobe_addr_list {
+       unsigned long *addrs;
+ };
+-static int fprobe_addr_list_add(struct fprobe_addr_list *alist, unsigned long addr)
++static int fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node,
++                                       struct fprobe_addr_list *alist)
+ {
+-      unsigned long *addrs;
+-
+-      /* Previously we failed to expand the list. */
+-      if (alist->index == alist->size)
+-              return -ENOSPC;
+-
+-      alist->addrs[alist->index++] = addr;
+-      if (alist->index < alist->size)
++      if (!within_module(node->addr, mod))
+               return 0;
+-      /* Expand the address list */
+-      addrs = kcalloc(alist->size * 2, sizeof(*addrs), GFP_KERNEL);
+-      if (!addrs)
+-              return -ENOMEM;
+-
+-      memcpy(addrs, alist->addrs, alist->size * sizeof(*addrs));
+-      alist->size *= 2;
+-      kfree(alist->addrs);
+-      alist->addrs = addrs;
++      if (delete_fprobe_node(node))
++              return 0;
++      /* If no address list is available, we can't track this address. */
++      if (!alist->addrs)
++              return 0;
++      alist->addrs[alist->index++] = node->addr;
++      if (alist->index == alist->size)
++              return -ENOSPC;
+       return 0;
+ }
+-static void fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node,
+-                                       struct fprobe_addr_list *alist)
+-{
+-      if (!within_module(node->addr, mod))
+-              return;
+-      if (delete_fprobe_node(node))
+-              return;
+-      /*
+-       * If failed to update alist, just continue to update hlist.
+-       * Therefore, at list user handler will not hit anymore.
+-       */
+-      fprobe_addr_list_add(alist, node->addr);
+-}
+-
+ /* Handle module unloading to manage fprobe_ip_table. */
+ static int fprobe_module_callback(struct notifier_block *nb,
+                                 unsigned long val, void *data)
+@@ -598,29 +575,50 @@ static int fprobe_module_callback(struct
+       struct fprobe_hlist_node *node;
+       struct rhashtable_iter iter;
+       struct module *mod = data;
++      bool retry;
+       if (val != MODULE_STATE_GOING)
+               return NOTIFY_DONE;
+       alist.addrs = kcalloc(alist.size, sizeof(*alist.addrs), GFP_KERNEL);
+-      /* If failed to alloc memory, we can not remove ips from hash. */
+-      if (!alist.addrs)
+-              return NOTIFY_DONE;
++      /*
++       * If failed to alloc memory, ftrace_ops will not be able to remove ips from
++       * hash, but we can still remove nodes from fprobe_ip_table, so we can avoid
++       * the potential wrong callback. So just print a warning here and try to
++       * continue without address list.
++       */
++      WARN_ONCE(!alist.addrs,
++              "Failed to allocate memory for fprobe_addr_list, ftrace_ops will not be updated");
+       mutex_lock(&fprobe_mutex);
++again:
++      retry = false;
++      alist.index = 0;
+       rhltable_walk_enter(&fprobe_ip_table, &iter);
+       do {
+               rhashtable_walk_start(&iter);
+               while ((node = rhashtable_walk_next(&iter)) && !IS_ERR(node))
+-                      fprobe_remove_node_in_module(mod, node, &alist);
++                      if (fprobe_remove_node_in_module(mod, node, &alist) < 0) {
++                              retry = true;
++                              break;
++                      }
+               rhashtable_walk_stop(&iter);
+-      } while (node == ERR_PTR(-EAGAIN));
++      } while (node == ERR_PTR(-EAGAIN) && !retry);
+       rhashtable_walk_exit(&iter);
++      /* Remove any ips from hash table(s) */
++      if (alist.index > 0) {
++              fprobe_remove_ips(alist.addrs, alist.index);
++              /*
++               * If we break rhashtable walk loop except for -EAGAIN, we need
++               * to restart looping from start for safety. Anyway, this is
++               * not a hotpath.
++               */
++              if (retry)
++                      goto again;
++      }
+-      if (alist.index > 0)
+-              fprobe_set_ips(alist.addrs, alist.index, 1, 0);
+       mutex_unlock(&fprobe_mutex);
+       kfree(alist.addrs);
diff --git a/queue-6.18/tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch b/queue-6.18/tracing-fprobe-check-the-same-type-fprobe-on-table-as-the-unregistered-one.patch
new file mode 100644 (file)
index 0000000..7a9e3ae
--- /dev/null
@@ -0,0 +1,207 @@
+From stable+bounces-253540-greg=kroah.com@vger.kernel.org Thu May 21 15:10:33 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 08:58:13 -0400
+Subject: tracing/fprobe: Check the same type fprobe on table as the unregistered one
+To: stable@vger.kernel.org
+Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260521125813.1165339-4-sashal@kernel.org>
+
+From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
+
+[ Upstream commit 0ac0058a74ac5765c7ce09ea630f4fdeaf4d80fa ]
+
+Commit 2c67dc457bc6 ("tracing: fprobe: optimization for entry only case")
+introduced a different ftrace_ops for entry-only fprobes.
+
+However, when unregistering an fprobe, the kernel only checks if another
+fprobe exists at the same address, without checking which type of fprobe
+it is.
+If different fprobes are registered at the same address, the same address
+will be registered in both fgraph_ops and ftrace_ops, but only one of
+them will be deleted when unregistering. (the one removed first will not
+be deleted from the ops).
+
+This results in junk entries remaining in either fgraph_ops or ftrace_ops.
+For example:
+ =======
+ cd /sys/kernel/tracing
+
+ # 'Add entry and exit events on the same place'
+ echo 'f:event1 vfs_read' >> dynamic_events
+ echo 'f:event2 vfs_read%return' >> dynamic_events
+
+ # 'Enable both of them'
+ echo 1 > events/fprobes/enable
+ cat enabled_functions
+vfs_read (2)            ->arch_ftrace_ops_list_func+0x0/0x210
+
+ # 'Disable and remove exit event'
+ echo 0 > events/fprobes/event2/enable
+ echo -:event2 >> dynamic_events
+
+ # 'Disable and remove all events'
+ echo 0 > events/fprobes/enable
+ echo > dynamic_events
+
+ # 'Add another event'
+ echo 'f:event3 vfs_open%return' > dynamic_events
+ cat dynamic_events
+f:fprobes/event3 vfs_open%return
+
+ echo 1 > events/fprobes/enable
+ cat enabled_functions
+vfs_open (1)            tramp: 0xffffffffa0001000 (ftrace_graph_func+0x0/0x60) ->ftrace_graph_func+0x0/0x60    subops: {ent:fprobe_fgraph_entry+0x0/0x620 ret:fprobe_return+0x0/0x150}
+vfs_read (1)            tramp: 0xffffffffa0001000 (ftrace_graph_func+0x0/0x60) ->ftrace_graph_func+0x0/0x60    subops: {ent:fprobe_fgraph_entry+0x0/0x620 ret:fprobe_return+0x0/0x150}
+ =======
+
+As you can see, an entry for the vfs_read remains.
+
+To fix this issue, when unregistering, the kernel should also check if
+there is the same type of fprobes still exist at the same address, and
+if not, delete its entry from either fgraph_ops or ftrace_ops.
+
+Link: https://lore.kernel.org/all/177669367993.132053.10553046138528674802.stgit@mhiramat.tok.corp.google.com/
+
+Fixes: 2c67dc457bc6 ("tracing: fprobe: optimization for entry only case")
+Cc: stable@vger.kernel.org
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/fprobe.c |   82 +++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 65 insertions(+), 17 deletions(-)
+
+--- a/kernel/trace/fprobe.c
++++ b/kernel/trace/fprobe.c
+@@ -92,11 +92,8 @@ static int insert_fprobe_node(struct fpr
+       return ret;
+ }
+-/* Return true if there are synonims */
+-static bool delete_fprobe_node(struct fprobe_hlist_node *node)
++static void delete_fprobe_node(struct fprobe_hlist_node *node)
+ {
+-      bool ret;
+-
+       lockdep_assert_held(&fprobe_mutex);
+       /* Avoid double deleting and non-inserted nodes */
+@@ -105,13 +102,6 @@ static bool delete_fprobe_node(struct fp
+               rhltable_remove(&fprobe_ip_table, &node->hlist,
+                               fprobe_rht_params);
+       }
+-
+-      rcu_read_lock();
+-      ret = !!rhltable_lookup(&fprobe_ip_table, &node->addr,
+-                              fprobe_rht_params);
+-      rcu_read_unlock();
+-
+-      return ret;
+ }
+ /* Check existence of the fprobe */
+@@ -343,6 +333,32 @@ static bool fprobe_is_ftrace(struct fpro
+       return !fp->exit_handler;
+ }
++static bool fprobe_exists_on_hash(unsigned long ip, bool ftrace)
++{
++      struct rhlist_head *head, *pos;
++      struct fprobe_hlist_node *node;
++      struct fprobe *fp;
++
++      guard(rcu)();
++      head = rhltable_lookup(&fprobe_ip_table, &ip,
++                              fprobe_rht_params);
++      if (!head)
++              return false;
++      /* We have to check the same type on the list. */
++      rhl_for_each_entry_rcu(node, pos, head, hlist) {
++              if (node->addr != ip)
++                      break;
++              fp = READ_ONCE(node->fp);
++              if (likely(fp)) {
++                      if ((!ftrace && fp->exit_handler) ||
++                          (ftrace && !fp->exit_handler))
++                              return true;
++              }
++      }
++
++      return false;
++}
++
+ #ifdef CONFIG_MODULES
+ static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt)
+ {
+@@ -365,6 +381,29 @@ static bool fprobe_is_ftrace(struct fpro
+       return false;
+ }
++static bool fprobe_exists_on_hash(unsigned long ip, bool ftrace __maybe_unused)
++{
++      struct rhlist_head *head, *pos;
++      struct fprobe_hlist_node *node;
++      struct fprobe *fp;
++
++      guard(rcu)();
++      head = rhltable_lookup(&fprobe_ip_table, &ip,
++                              fprobe_rht_params);
++      if (!head)
++              return false;
++      /* We only need to check fp is there. */
++      rhl_for_each_entry_rcu(node, pos, head, hlist) {
++              if (node->addr != ip)
++                      break;
++              fp = READ_ONCE(node->fp);
++              if (likely(fp))
++                      return true;
++      }
++
++      return false;
++}
++
+ #ifdef CONFIG_MODULES
+ static void fprobe_remove_ips(unsigned long *ips, unsigned int cnt)
+ {
+@@ -552,18 +591,25 @@ struct fprobe_addr_list {
+ static int fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node,
+                                        struct fprobe_addr_list *alist)
+ {
++      lockdep_assert_in_rcu_read_lock();
++
+       if (!within_module(node->addr, mod))
+               return 0;
+-      if (delete_fprobe_node(node))
+-              return 0;
++      delete_fprobe_node(node);
+       /* If no address list is available, we can't track this address. */
+       if (!alist->addrs)
+               return 0;
++      /*
++       * Don't care the type here, because all fprobes on the same
++       * address must be removed eventually.
++       */
++      if (!rhltable_lookup(&fprobe_ip_table, &node->addr, fprobe_rht_params)) {
++              alist->addrs[alist->index++] = node->addr;
++              if (alist->index == alist->size)
++                      return -ENOSPC;
++      }
+-      alist->addrs[alist->index++] = node->addr;
+-      if (alist->index == alist->size)
+-              return -ENOSPC;
+       return 0;
+ }
+@@ -934,7 +980,9 @@ static int unregister_fprobe_nolock(stru
+       /* Remove non-synonim ips from table and hash */
+       count = 0;
+       for (i = 0; i < hlist_array->size; i++) {
+-              if (!delete_fprobe_node(&hlist_array->array[i]) && addrs)
++              delete_fprobe_node(&hlist_array->array[i]);
++              if (addrs && !fprobe_exists_on_hash(hlist_array->array[i].addr,
++                                                  fprobe_is_ftrace(fp)))
+                       addrs[count++] = hlist_array->array[i].addr;
+       }
+       del_fprobe_hash(fp);
diff --git a/queue-6.18/tracing-fprobe-remove-unused-local-variable.patch b/queue-6.18/tracing-fprobe-remove-unused-local-variable.patch
new file mode 100644 (file)
index 0000000..cc320b8
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-253536-greg=kroah.com@vger.kernel.org Thu May 21 15:10:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 08:58:10 -0400
+Subject: tracing: fprobe: Remove unused local variable
+To: stable@vger.kernel.org
+Cc: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>, Menglong Dong <menglong8.dong@gmail.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260521125813.1165339-1-sashal@kernel.org>
+
+From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
+
+[ Upstream commit 90e69d291d195d35215b578d210fd3ce0e5a3f42 ]
+
+The 'ret' local variable in fprobe_remove_node_in_module() was used
+for checking the error state in the loop, but commit dfe0d675df82
+("tracing: fprobe: use rhltable for fprobe_ip_table") removed the loop.
+So we don't need it anymore.
+
+Link: https://lore.kernel.org/all/175867358989.600222.6175459620045800878.stgit@devnote2/
+
+Fixes: e5a4cc28a052 ("tracing: fprobe: use rhltable for fprobe_ip_table")
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Acked-by: Menglong Dong <menglong8.dong@gmail.com>
+Stable-dep-of: 0ac0058a74ac ("tracing/fprobe: Check the same type fprobe on table as the unregistered one")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/fprobe.c |    5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/kernel/trace/fprobe.c
++++ b/kernel/trace/fprobe.c
+@@ -561,8 +561,6 @@ static int fprobe_addr_list_add(struct f
+ static void fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node,
+                                        struct fprobe_addr_list *alist)
+ {
+-      int ret = 0;
+-
+       if (!within_module(node->addr, mod))
+               return;
+       if (delete_fprobe_node(node))
+@@ -571,8 +569,7 @@ static void fprobe_remove_node_in_module
+        * If failed to update alist, just continue to update hlist.
+        * Therefore, at list user handler will not hit anymore.
+        */
+-      if (!ret)
+-              ret = fprobe_addr_list_add(alist, node->addr);
++      fprobe_addr_list_add(alist, node->addr);
+ }
+ /* Handle module unloading to manage fprobe_ip_table. */
diff --git a/queue-6.18/tracing-fprobe-use-ftrace-if-config_dynamic_ftrace_with_args.patch b/queue-6.18/tracing-fprobe-use-ftrace-if-config_dynamic_ftrace_with_args.patch
new file mode 100644 (file)
index 0000000..fe28591
--- /dev/null
@@ -0,0 +1,110 @@
+From stable+bounces-253538-greg=kroah.com@vger.kernel.org Thu May 21 15:50:39 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 08:58:11 -0400
+Subject: tracing: fprobe: use ftrace if CONFIG_DYNAMIC_FTRACE_WITH_ARGS
+To: stable@vger.kernel.org
+Cc: Menglong Dong <menglong8.dong@gmail.com>, Menglong Dong <dongml2@chinatelecom.cn>, "Masami Hiramatsu (Google)" <mhiramat@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260521125813.1165339-2-sashal@kernel.org>
+
+From: Menglong Dong <menglong8.dong@gmail.com>
+
+[ Upstream commit cd06078a38aaedfebbf8fa0c009da0f99f4473fb ]
+
+For now, we will use ftrace for the fprobe if fp->exit_handler not exists
+and CONFIG_DYNAMIC_FTRACE_WITH_REGS is enabled.
+
+However, CONFIG_DYNAMIC_FTRACE_WITH_REGS is not supported by some arch,
+such as arm. What we need in the fprobe is the function arguments, so we
+can use ftrace for fprobe if CONFIG_DYNAMIC_FTRACE_WITH_ARGS is enabled.
+
+Therefore, use ftrace if CONFIG_DYNAMIC_FTRACE_WITH_REGS or
+CONFIG_DYNAMIC_FTRACE_WITH_ARGS enabled.
+
+Link: https://lore.kernel.org/all/20251103063434.47388-1-dongml2@chinatelecom.cn/
+
+Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Stable-dep-of: 0ac0058a74ac ("tracing/fprobe: Check the same type fprobe on table as the unregistered one")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/fprobe.c |   32 ++++++++++++++++++++++----------
+ 1 file changed, 22 insertions(+), 10 deletions(-)
+
+--- a/kernel/trace/fprobe.c
++++ b/kernel/trace/fprobe.c
+@@ -45,6 +45,7 @@
+ static struct hlist_head fprobe_table[FPROBE_TABLE_SIZE];
+ static struct rhltable fprobe_ip_table;
+ static DEFINE_MUTEX(fprobe_mutex);
++static struct fgraph_ops fprobe_graph_ops;
+ static u32 fprobe_node_hashfn(const void *data, u32 len, u32 seed)
+ {
+@@ -259,7 +260,7 @@ static inline int __fprobe_kprobe_handle
+       return ret;
+ }
+-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
++#if defined(CONFIG_DYNAMIC_FTRACE_WITH_ARGS) || defined(CONFIG_DYNAMIC_FTRACE_WITH_REGS)
+ /* ftrace_ops callback, this processes fprobes which have only entry_handler. */
+ static void fprobe_ftrace_entry(unsigned long ip, unsigned long parent_ip,
+       struct ftrace_ops *ops, struct ftrace_regs *fregs)
+@@ -300,7 +301,7 @@ NOKPROBE_SYMBOL(fprobe_ftrace_entry);
+ static struct ftrace_ops fprobe_ftrace_ops = {
+       .func   = fprobe_ftrace_entry,
+-      .flags  = FTRACE_OPS_FL_SAVE_REGS,
++      .flags  = FTRACE_OPS_FL_SAVE_ARGS,
+ };
+ static int fprobe_ftrace_active;
+@@ -341,6 +342,15 @@ static bool fprobe_is_ftrace(struct fpro
+ {
+       return !fp->exit_handler;
+ }
++
++#ifdef CONFIG_MODULES
++static void fprobe_set_ips(unsigned long *ips, unsigned int cnt, int remove,
++                         int reset)
++{
++      ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, remove, reset);
++      ftrace_set_filter_ips(&fprobe_ftrace_ops, ips, cnt, remove, reset);
++}
++#endif
+ #else
+ static int fprobe_ftrace_add_ips(unsigned long *addrs, int num)
+ {
+@@ -355,7 +365,15 @@ static bool fprobe_is_ftrace(struct fpro
+ {
+       return false;
+ }
++
++#ifdef CONFIG_MODULES
++static void fprobe_set_ips(unsigned long *ips, unsigned int cnt, int remove,
++                         int reset)
++{
++      ftrace_set_filter_ips(&fprobe_graph_ops.ops, ips, cnt, remove, reset);
++}
+ #endif
++#endif /* !CONFIG_DYNAMIC_FTRACE_WITH_ARGS && !CONFIG_DYNAMIC_FTRACE_WITH_REGS */
+ /* fgraph_ops callback, this processes fprobes which have exit_handler. */
+ static int fprobe_fgraph_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops,
+@@ -601,14 +619,8 @@ static int fprobe_module_callback(struct
+       } while (node == ERR_PTR(-EAGAIN));
+       rhashtable_walk_exit(&iter);
+-      if (alist.index > 0) {
+-              ftrace_set_filter_ips(&fprobe_graph_ops.ops,
+-                                    alist.addrs, alist.index, 1, 0);
+-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+-              ftrace_set_filter_ips(&fprobe_ftrace_ops,
+-                                    alist.addrs, alist.index, 1, 0);
+-#endif
+-      }
++      if (alist.index > 0)
++              fprobe_set_ips(alist.addrs, alist.index, 1, 0);
+       mutex_unlock(&fprobe_mutex);
+       kfree(alist.addrs);