lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20250918125241.80968-1-zhoujinghao24b@gmail.com>
Date: Thu, 18 Sep 2025 20:52:41 +0800
From: Jinghao Zhou <zhoujinghao24b@...il.com>
To: linux-pm@...r.kernel.org
Cc: rafael@...nel.org,
	viresh.kumar@...aro.org,
	linux-kernel@...r.kernel.org,
	zouyipeng@...wei.com,
	Jinghao Zhou <zhoujinghao24b@...il.com>
Subject: [PATCH] cpufreq: ext: fix NULL deref in ext_gov_update()

Switching to the 'ext' governor can trigger a NULL pointer dereference
in ext_gov_update().

Two problems were present in this function:
  1) policy_dbs was derived via container_of(policy, ...), which is not
     a valid way to obtain CPUFreq dbs-governor per-policy state. Use
     policy->governor_data instead.
  2) When the BPF hook returns 0 for get_sampling_rate, the code fell
     back to gov->gdbs_data->sampling_rate, which may be NULL or stale
     depending on initialization/teardown ordering. The robust pattern
     is to fetch the per-policy sampling rate from policy_dbs->dbs_data.

This patch switches ext_gov_update() to the per-policy path
(policy->governor_data -> policy_dbs->dbs_data) and adds minimal NULL
checks. After this change, switching to the 'ext' governor no longer
panics in testing.

Observed on: Pixel 6 (oriole, arm64), Android kernel
  6.12.0-mainline-g0a53f54ba5c5 (Jun 11, 2025), after applying the
  cpufreq_ext RFC series. Also revalidated on a PC build.

Reproducer:
  for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do
      echo ext > "$cpu"
  done

Link: https://lore.kernel.org/linux-pm/20240927101342.3240263-1-zouyipeng@huawei.com/
Signed-off-by: Jinghao Zhou <zhoujinghao24b@...il.com>
---
 drivers/cpufreq/cpufreq_ext.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/cpufreq/cpufreq_ext.c b/drivers/cpufreq/cpufreq_ext.c
index 310f13aca70a..c79068e86c27 100644
--- a/drivers/cpufreq/cpufreq_ext.c
+++ b/drivers/cpufreq/cpufreq_ext.c
@@ -409,11 +409,18 @@ static unsigned int ext_gov_update(struct cpufreq_policy *policy)
 {
 	struct ext_policy *ext;
 	struct policy_dbs_info *policy_dbs;
+	struct dbs_data *dbs_data;
 	unsigned int update_sampling_rate = 0;
-	struct dbs_governor *gov = dbs_governor_of(policy);
 
-	/* Only need to update current policy freq */
-	policy_dbs = container_of((void *)policy, struct policy_dbs_info, policy);
+	/* Get policy_dbs_info from policy's governor_data */
+	policy_dbs = policy->governor_data;
+	if (!policy_dbs)
+		return 0;
+
+	/* Get dbs_data directly from policy_dbs for better stability */
+	dbs_data = policy_dbs->dbs_data;
+	if (!dbs_data)
+		return 0;
 
 	ext = to_ext_policy(policy_dbs);
 
@@ -431,7 +438,7 @@ static unsigned int ext_gov_update(struct cpufreq_policy *policy)
 		update_sampling_rate = ext_ops_global.get_sampling_rate(policy);
 
 	/* If get_sampling_rate return 0, means we don't modify sampling_rate any more. */
-	return update_sampling_rate == 0 ? gov->gdbs_data->sampling_rate : update_sampling_rate;
+	return update_sampling_rate == 0 ? dbs_data->sampling_rate : update_sampling_rate;
 }
 
 static struct policy_dbs_info *ext_gov_alloc(void)
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ