linux-hardened/drivers
Viresh Kumar 6ffae8c06f cpufreq: Set cpufreq_cpu_data to NULL before putting kobject
In __cpufreq_remove_dev_finish(), per-cpu 'cpufreq_cpu_data' needs
to be cleared before calling kobject_put(&policy->kobj) and under
cpufreq_driver_lock. Otherwise, if someone else calls cpufreq_cpu_get()
in parallel with it, they can obtain a non-NULL policy from that after
kobject_put(&policy->kobj) was executed.

Consider this case:

Thread A				Thread B
cpufreq_cpu_get()
  acquire cpufreq_driver_lock
  read-per-cpu cpufreq_cpu_data
					kobject_put(&policy->kobj);
  kobject_get(&policy->kobj);
					...
					per_cpu(&cpufreq_cpu_data, cpu) = NULL

And this will result in a warning like this one:

 ------------[ cut here ]------------
 WARNING: CPU: 0 PID: 4 at include/linux/kref.h:47
 kobject_get+0x41/0x50()
 Modules linked in: acpi_cpufreq(+) nfsd auth_rpcgss nfs_acl
 lockd grace sunrpc xfs libcrc32c sd_mod ixgbe igb mdio ahci hwmon
 ...
 Call Trace:
  [<ffffffff81661b14>] dump_stack+0x46/0x58
  [<ffffffff81072b61>] warn_slowpath_common+0x81/0xa0
  [<ffffffff81072c7a>] warn_slowpath_null+0x1a/0x20
  [<ffffffff812e16d1>] kobject_get+0x41/0x50
  [<ffffffff815262a5>] cpufreq_cpu_get+0x75/0xc0
  [<ffffffff81527c3e>] cpufreq_update_policy+0x2e/0x1f0
  [<ffffffff810b8cb2>] ? up+0x32/0x50
  [<ffffffff81381aa9>] ? acpi_ns_get_node+0xcb/0xf2
  [<ffffffff81381efd>] ? acpi_evaluate_object+0x22c/0x252
  [<ffffffff813824f6>] ? acpi_get_handle+0x95/0xc0
  [<ffffffff81360967>] ? acpi_has_method+0x25/0x40
  [<ffffffff81391e08>] acpi_processor_ppc_has_changed+0x77/0x82
  [<ffffffff81089566>] ? move_linked_works+0x66/0x90
  [<ffffffff8138e8ed>] acpi_processor_notify+0x58/0xe7
  [<ffffffff8137410c>] acpi_ev_notify_dispatch+0x44/0x5c
  [<ffffffff8135f293>] acpi_os_execute_deferred+0x15/0x22
  [<ffffffff8108c910>] process_one_work+0x160/0x410
  [<ffffffff8108d05b>] worker_thread+0x11b/0x520
  [<ffffffff8108cf40>] ? rescuer_thread+0x380/0x380
  [<ffffffff81092421>] kthread+0xe1/0x100
  [<ffffffff81092340>] ? kthread_create_on_node+0x1b0/0x1b0
  [<ffffffff81669ebc>] ret_from_fork+0x7c/0xb0
  [<ffffffff81092340>] ? kthread_create_on_node+0x1b0/0x1b0
 ---[ end trace 89e66eb9795efdf7 ]---

The actual code flow is as follows:

 Thread A: Workqueue: kacpi_notify

 acpi_processor_notify()
   acpi_processor_ppc_has_changed()
         cpufreq_update_policy()
           cpufreq_cpu_get()
             kobject_get()

 Thread B: xenbus_thread()

 xenbus_thread()
   msg->u.watch.handle->callback()
     handle_vcpu_hotplug_event()
       vcpu_hotplug()
         cpu_down()
           __cpu_notify(CPU_POST_DEAD..)
             cpufreq_cpu_callback()
               __cpufreq_remove_dev_finish()
                 cpufreq_policy_put_kobj()
                   kobject_put()

cpufreq_cpu_get() gets the policy from per-cpu variable cpufreq_cpu_data
under cpufreq_driver_lock, and once it gets a valid policy it expects it
to not be freed until cpufreq_cpu_put() is called.

But the race happens when another thread puts the kobject first and updates
cpufreq_cpu_data before or later. And so the first thread gets a valid policy
structure and before it does kobject_get() on it, the second one has already
done kobject_put().

Fix this by setting cpufreq_cpu_data to NULL before putting the kobject and that
too under locks.

Reported-by: Ethan Zhao <ethan.zhao@oracle.com>
Reported-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Cc: 3.12+ <stable@vger.kernel.org> # 3.12+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2015-02-03 00:59:29 +01:00
..
accessibility
acpi Merge branch 'for-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux 2015-01-14 07:53:51 +13:00
amba Char/Misc driver patches for 3.19-rc1 2014-12-14 16:43:47 -08:00
android
ata More ACPI and power management updates for 3.19-rc1 2014-12-18 20:28:33 -08:00
atm Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
auxdisplay
base Merge branches 'pm-domains', 'powercap' and 'pm-tools' 2014-12-29 21:24:00 +01:00
bcma Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus 2014-12-11 17:56:37 -08:00
block NVMe: Fix locking on abort handling 2015-01-08 09:02:23 -07:00
bluetooth Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next 2014-12-15 13:23:09 -05:00
bus drivers: bus: check cci device tree node status 2015-01-16 19:10:41 -08:00
cdrom
char ipmi: Fix compile warning with tv_usec 2014-12-30 13:34:36 -06:00
clk clk: fix possible null pointer dereference 2015-01-17 11:33:57 -08:00
clocksource Fixes for 3.19 2014-12-30 15:27:20 +01:00
connector
coresight
cpufreq cpufreq: Set cpufreq_cpu_data to NULL before putting kobject 2015-02-03 00:59:29 +01:00
cpuidle Merge branches 'pm-cpufreq' and 'pm-cpuidle' 2014-12-29 21:23:41 +01:00
crypto Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
dca
devfreq
dio
dma dmaengine: dw: balance PM runtime calls 2015-01-13 23:07:58 +05:30
dma-buf
edac Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
eisa
extcon Char/Misc driver patches for 3.19-rc1 2014-12-14 16:43:47 -08:00
firewire firewire: sbp2: replace card lock by target lock 2014-12-10 20:53:21 +01:00
firmware Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
fmc
gpio gpio: dln2: use bus_sync_unlock instead of scheduling work 2015-01-09 07:57:35 +01:00
gpu Merge tag 'amdkfd-fixes-2015-01-06' of git://people.freedesktop.org/~gabbayo/linux into drm-fixes 2015-01-08 10:36:37 +10:00
hid HID: roccat: potential out of bounds in pyra_sysfs_write_settings() 2015-01-09 14:41:01 +01:00
hsi * misc. fixes in omap-ssi and nokia-modem drivers 2014-12-15 17:33:47 -08:00
hv Char/Misc driver patches for 3.19-rc1 2014-12-14 16:43:47 -08:00
hwmon Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux 2014-12-17 10:16:27 -08:00
hwspinlock
i2c Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux 2014-12-20 13:52:52 -08:00
ide Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
idle
iio First round of IIO fixes for the 3.19 cycle. 2015-01-08 17:59:04 -08:00
infiniband SCSI for-linus on 20141220 2014-12-20 13:42:57 -08:00
input Revert "Input: atmel_mxt_ts - use deep sleep mode when stopped" 2014-12-31 12:59:34 -08:00
iommu iommu/rockchip: Drop owner assignment from platform_drivers 2015-01-05 12:40:06 +01:00
ipack
irqchip Merge branch 'irq-irqdomain-arm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-12-15 17:30:09 -08:00
isdn isdn: fix NUL (\0 or \x00) specification in string 2015-01-12 15:31:35 -05:00
leds leds: netxbig: fix oops at probe time 2015-01-13 13:49:01 -08:00
lguest virtio: allow finalize_features to fail 2014-12-09 16:32:32 +02:00
macintosh macintosh: therm_pm72: delete deprecated driver 2014-12-19 19:32:47 +01:00
mailbox Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
mcb mcb: mcb-pci: Only remap the 1st 0x200 bytes of BAR 0 2015-01-09 15:46:37 -08:00
md dm: fix missed error code if .end_io isn't implemented by target_type 2014-12-17 12:31:13 -05:00
media More ACPI and power management updates for 3.19-rc1 2014-12-18 20:28:33 -08:00
memory MTD updates for 3.19: 2014-12-17 09:59:26 -08:00
memstick
message
mfd Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input 2014-12-30 16:59:59 -08:00
misc Char/Misc driver fixes for 3.19-rc5 2015-01-17 08:18:08 +13:00
mmc mmc: sdhci: Set SDHCI_POWER_ON with external vmmc 2015-01-14 09:47:19 +01:00
mtd MTD updates for 3.19: 2014-12-17 09:59:26 -08:00
net tg3: Release tp->lock before invoking synchronize_irq() 2015-01-14 17:05:51 -05:00
nfc More ACPI and power management updates for 3.19-rc1 2014-12-18 20:28:33 -08:00
ntb
nubus
of ARM: SoC/iommu configuration for 3.19 2014-12-16 14:53:01 -08:00
oprofile
parisc
parport Char/Misc driver patches for 3.19-rc1 2014-12-14 16:43:47 -08:00
pci Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2014-12-19 14:02:02 -08:00
pcmcia Char/Misc driver patches for 3.19-rc1 2014-12-14 16:43:47 -08:00
phy phy: phy-ti-pipe3: fix inconsistent enumeration of PCIe gen2 cards 2014-12-23 15:44:32 +05:30
pinctrl pinctrl: st: Add irq_disable hook to st_gpio_irqchip 2015-01-07 10:44:39 +01:00
platform platform-drivers-x86 for 3.19 2014-12-18 20:24:55 -08:00
pnp
power More ACPI and power management updates for 3.19-rc1 2014-12-18 20:28:33 -08:00
powercap powercap / RAPL: add IDs for future Xeon CPUs 2014-12-17 02:35:42 +01:00
pps
ps3
ptp
pwm pwm: Changes for v3.19-rc1 2014-12-17 10:10:51 -08:00
rapidio
ras
regulator regulator: Fix for v3.19 2014-12-29 13:24:38 -08:00
remoteproc Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
reset reset: sunxi: fix spinlock initialization 2015-01-16 19:11:31 -08:00
rpmsg
rtc Driver core patches for 3.19-rc1 2014-12-14 16:10:09 -08:00
s390 s390/zcrypt: kernel oops at insmod of the z90crypt device driver 2014-12-18 09:55:55 +01:00
sbus
scsi scsi: ->queue_rq can't sleep 2015-01-09 15:43:01 +01:00
sfi
sh drivers: sh / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM 2014-12-05 03:08:24 +01:00
sn
soc Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux 2014-12-15 15:52:01 -08:00
spi Merge remote-tracking branches 'spi/fix/img-spfi' and 'spi/fix/msiof' into spi-linus 2014-12-24 12:57:54 +00:00
spmi
ssb Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus 2014-12-11 17:56:37 -08:00
staging staging: vt6655: fix sparse warning: argument type 2015-01-12 19:49:47 -08:00
target iscsi-target: Fix typos in enum cmd_flags_table 2015-01-09 15:25:58 -08:00
tc
thermal Merge branch 'thermal-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux 2015-01-15 19:20:26 +13:00
thunderbolt
tty serial: samsung: Add the support for Exynos5433 SoC 2015-01-09 13:46:02 -08:00
uio Char/Misc driver patches for 3.19-rc1 2014-12-14 16:43:47 -08:00
usb usb: fixes for v3.19-rc6 2015-01-14 16:27:23 -08:00
uwb
vfio vfio-pci: Fix the check on pci device type in vfio_pci_probe() 2015-01-07 10:29:11 -07:00
vhost Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending 2015-01-13 15:23:26 +13:00
video fbdev/broadsheetfb: fix memory leak 2015-01-13 15:13:45 +02:00
virt
virtio virtio_pci: document why we defer kfree 2015-01-06 16:35:36 +02:00
vlynq
vme
w1 Char/Misc driver patches for 3.19-rc1 2014-12-14 16:43:47 -08:00
watchdog watchdog: imx2_wdt: Fix the argument of watchdog_active() 2014-12-18 16:01:20 +01:00
xen Merge remote-tracking branch 'scsi-queue/drivers-for-3.19' into for-linus 2014-12-18 05:56:29 -08:00
zorro
Kconfig Staging patches for 3.19-rc1 2014-12-15 18:06:13 -08:00
Makefile drivers: Move iommu/ before gpu/ in Makefile 2014-12-22 11:47:37 +02:00