Skip to content

Commit

Permalink
powerpc/perf: Fix kernel address leak via sampling registers
Browse files Browse the repository at this point in the history
Current code in power_pmu_disable() does not clear the sampling
registers like Sampling Instruction Address Register (SIAR) and
Sampling Data Address Register (SDAR) after disabling the PMU. Since
these are userspace readable and could contain kernel addresses, add
code to explicitly clear the content of these registers.

Also add a "context synchronizing instruction" to enforce no further
updates to these registers as suggested by Power ISA v3.0B. From
section 9.4, on page 1108:

  "If an mtspr instruction is executed that changes the value of a
  Performance Monitor register other than SIAR, SDAR, and SIER, the
  change is not guaranteed to have taken effect until after a
  subsequent context synchronizing instruction has been executed (see
  Chapter 11. "Synchronization Requirements for Context Alterations"
  on page 1133)."

Signed-off-by: Madhavan Srinivasan <[email protected]>
[mpe: Massage change log and add ISA reference]
Signed-off-by: Michael Ellerman <[email protected]>
  • Loading branch information
mpe committed Mar 27, 2018
1 parent dbfcf3c commit e1ebd0e
Showing 1 changed file with 15 additions and 0 deletions.
15 changes: 15 additions & 0 deletions arch/powerpc/perf/core-book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,7 @@ static void power_pmu_disable(struct pmu *pmu)
*/
write_mmcr0(cpuhw, val);
mb();
isync();

/*
* Disable instruction sampling if it was enabled
Expand All @@ -1234,12 +1235,26 @@ static void power_pmu_disable(struct pmu *pmu)
mtspr(SPRN_MMCRA,
cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE);
mb();
isync();
}

cpuhw->disabled = 1;
cpuhw->n_added = 0;

ebb_switch_out(mmcr0);

#ifdef CONFIG_PPC64
/*
* These are readable by userspace, may contain kernel
* addresses and are not switched by context switch, so clear
* them now to avoid leaking anything to userspace in general
* including to another process.
*/
if (ppmu->flags & PPMU_ARCH_207S) {
mtspr(SPRN_SDAR, 0);
mtspr(SPRN_SIAR, 0);
}
#endif
}

local_irq_restore(flags);
Expand Down

0 comments on commit e1ebd0e

Please sign in to comment.