From dca026139317dcbc642a30320d551f559692182f Mon Sep 17 00:00:00 2001 From: Lothar Waßmann Date: Thu, 29 May 2008 17:54:52 +0200 Subject: [CPUFREQ] fix double unlock of cpu_policy_rwsem in drivers/cpufreq/cpufreq.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In drivers/cpufreq/cpufreq.c the function cpufreq_add_dev() takes the error exit 'err_out_unregister' from different places once with the 'cpu_policy_rwsem' lock held, once with the lock released: | if (ret) | goto err_out_unregister; | } | | policy->governor = NULL; /* to assure that the starting sequence is | * run in cpufreq_set_policy */ | | /* set default policy */ | ret = __cpufreq_set_policy(policy, &new_policy); | policy->user_policy.policy = policy->policy; | policy->user_policy.governor = policy->governor; | | unlock_policy_rwsem_write(cpu); | | if (ret) { | dprintk("setting policy failed\n"); | goto err_out_unregister; | } This leads to the following error message in case of a failing __cpufreq_set_policy() call: ===================================== [ BUG: bad unlock balance detected! ] ------------------------------------- swapper/1 is trying to release lock (&per_cpu(cpu_policy_rwsem, cpu)) at: [] unlock_policy_rwsem_write+0x30/0x40 but there are no more locks to release! other info that might help us debug this: 1 lock held by swapper/1: #0: (sysdev_drivers_lock){--..}, at: [] sysdev_driver_register+0x74/0x130 stack backtrace: [] (dump_stack+0x0/0x14) from [] (print_unlock_inbalance_bug+0xc8/0x104) [] (print_unlock_inbalance_bug+0x0/0x104) from [] (lock_release_non_nested+0xc4/0x19c) r6:00000028 r5:c3c1ab80 r4:c01b4564 [] (lock_release_non_nested+0x0/0x19c) from [] (lock_release+0x15c/0x18c) r8:60000013 r7:00000001 r6:c01b4564 r5:c0541bb4 r4:c3c1ab80 [] (lock_release+0x0/0x18c) from [] (up_write+0x24/0x30) r8:c0541b80 r7:00000000 r6:ffffffea r5:c3c34828 r4:c0541b8c [] (up_write+0x0/0x30) from [] (unlock_policy_rwsem_write+0x30/0x40) r4:c3c34884 [] (unlock_policy_rwsem_write+0x0/0x40) from [] (cpufreq_add_dev+0x324/0x398) [] (cpufreq_add_dev+0x0/0x398) from [] (sysdev_driver_register+0xc0/0x130) [] (sysdev_driver_register+0x0/0x130) from [] (cpufreq_register_driver+0xbc/0x174) Signed-off-by: Lothar Waßmann Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/cpufreq/cpufreq.c') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7fce038fa57e..86f0a2430624 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -928,13 +928,13 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) policy->user_policy.policy = policy->policy; policy->user_policy.governor = policy->governor; - unlock_policy_rwsem_write(cpu); - if (ret) { dprintk("setting policy failed\n"); goto err_out_unregister; } + unlock_policy_rwsem_write(cpu); + kobject_uevent(&policy->kobj, KOBJ_ADD); module_put(cpufreq_driver->owner); dprintk("initialization complete\n"); -- cgit v1.2.3 From 879000f94442860e72c934f9e568989bc7fb8ec4 Mon Sep 17 00:00:00 2001 From: CHIKAMA masaki Date: Thu, 5 Jun 2008 22:46:33 -0700 Subject: cpufreq: fix null object access on Transmeta CPU If cpu specific cpufreq driver(i.e. longrun) has "setpolicy" function, governor object isn't set into cpufreq_policy object at "__cpufreq_set_policy" function in driver/cpufreq/cpufreq.c . This causes a null object access at "store_scaling_setspeed" and "show_scaling_setspeed" function in driver/cpufreq/cpufreq.c when reading or writing through /sys interface (ex. cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed) Addresses: http://bugzilla.kernel.org/show_bug.cgi?id=10654 https://bugzilla.redhat.com/show_bug.cgi?id=443354 Signed-off-by: CHIKAMA Masaki Cc: Dave Jones Cc: Chuck Ebbert Acked-by: Dominik Brodowski Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/cpufreq/cpufreq.c') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 86f0a2430624..4e07d1f43a43 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -625,7 +625,7 @@ static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, unsigned int freq = 0; unsigned int ret; - if (!policy->governor->store_setspeed) + if (!policy->governor || !policy->governor->store_setspeed) return -EINVAL; ret = sscanf(buf, "%u", &freq); @@ -639,7 +639,7 @@ static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) { - if (!policy->governor->show_setspeed) + if (!policy->governor || !policy->governor->show_setspeed) return sprintf(buf, "\n"); return policy->governor->show_setspeed(policy, buf); -- cgit v1.2.3 From 326f6a5c9c9e1a62aec37bdc0c3f8d53adabe77b Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Fri, 6 Jun 2008 21:26:02 -0700 Subject: [CPUFREQ] Fix format string bug. Format string bug. Not exploitable, as this is only writable by root, but worth fixing all the same. Spotted-by: Ilja van Sprundel Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/cpufreq/cpufreq.c') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 86f0a2430624..cc3baf10d2d0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -412,7 +412,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, int ret; mutex_unlock(&cpufreq_governor_mutex); - ret = request_module(name); + ret = request_module("%s", name); mutex_lock(&cpufreq_governor_mutex); if (ret == 0) -- cgit v1.2.3