summaryrefslogtreecommitdiff
path: root/arch/arm/vfp
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2012-04-14 23:20:30 +0300
committerVarun Wadekar <vwadekar@nvidia.com>2012-07-09 03:01:35 -0700
commit01789ac917c80e54c2ba98d7221e3726b218127b (patch)
tree0e71eca1de180a9d231e14931eb8853143b40ee2 /arch/arm/vfp
parentd990c395f9c80572bb97f065adf5090ba28fde0e (diff)
arm: vfp: Fix memory corruption on PM suspend
Commit 36af2a47 ("ARM: vfp: Always save VFP state in vfp_pm_suspend") introduced a potential use-after-free bug. On SMP systems, vfp_current_hw_state might hold dangling pointers in case a task which used the VFP last migrates to another CPU and then exits. If vfp_pm_suspend is called while vfp_current_hw_state still holds a pointer to the freed thread_info, that memory location will be written, potentially overwriting a new object allocated there. The original problem is only relevant to UP systems in which the VFP state is stored lazily. Fix this by only storing the VFP state on UP systems, and avoid doing so on SMP ones. Change-Id: I8f7026eb735b340fcef4cf12fbd12b9a0ea08d3f Signed-off-by: Ido Yariv <ido@wizery.com> Signed-off-by: Eyal Shapira <eyal@wizery.com> Signed-off-by: Colin Cross <ccross@android.com> Reviewed-on: http://git-master/r/114167 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com> Tested-by: Prashant Gaikwad <pgaikwad@nvidia.com> Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r--arch/arm/vfp/vfpmodule.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 93e19fb566f4..2a4630ad8e7e 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -458,9 +458,11 @@ static int vfp_pm_suspend(void)
/* disable, just in case */
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
} else if (vfp_current_hw_state[ti->cpu]) {
+#ifndef CONFIG_SMP
fmxr(FPEXC, fpexc | FPEXC_EN);
vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc);
fmxr(FPEXC, fpexc);
+#endif
}
/* clear any information we had about last context state */