git: 8837e9c54072 - stable/13 - arm64: validate breakpoint registers
Mitchell Horne
mhorne at FreeBSD.org
Wed Feb 24 15:02:42 UTC 2021
The branch stable/13 has been updated by mhorne:
URL: https://cgit.FreeBSD.org/src/commit/?id=8837e9c54072679b69ae0c0345e7ef7d241255aa
commit 8837e9c54072679b69ae0c0345e7ef7d241255aa
Author: Mitchell Horne <mhorne at FreeBSD.org>
AuthorDate: 2021-02-09 18:29:38 +0000
Commit: Mitchell Horne <mhorne at FreeBSD.org>
CommitDate: 2021-02-24 14:57:04 +0000
arm64: validate breakpoint registers
In particular, we want to disallow setting breakpoints on kernel
addresses from userspace. The control register fields are validated or
ignored as appropriate.
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
(cherry picked from commit de2b9422807586d376ec7ffa7b660cd492464bdf)
---
sys/arm64/arm64/machdep.c | 37 +++++++++++++++++++++++++++++++++----
sys/arm64/include/armreg.h | 17 +++++++++++++++++
2 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index 90fc19d57415..bf44dba19482 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -357,6 +357,8 @@ int
set_dbregs(struct thread *td, struct dbreg *regs)
{
struct debug_monitor_state *monitor;
+ uint64_t addr;
+ uint32_t ctrl;
int count;
int i;
@@ -364,11 +366,38 @@ set_dbregs(struct thread *td, struct dbreg *regs)
count = 0;
monitor->dbg_enable_count = 0;
for (i = 0; i < DBG_BRP_MAX; i++) {
- /* TODO: Check these values */
- monitor->dbg_bvr[i] = regs->db_regs[i].dbr_addr;
- monitor->dbg_bcr[i] = regs->db_regs[i].dbr_ctrl;
- if ((monitor->dbg_bcr[i] & 1) != 0)
+ addr = regs->db_regs[i].dbr_addr;
+ ctrl = regs->db_regs[i].dbr_ctrl;
+
+ /* Don't let the user set a breakpoint on a kernel address. */
+ if (addr >= VM_MAXUSER_ADDRESS)
+ return (EINVAL);
+
+ /*
+ * The lowest 2 bits are ignored, so record the effective
+ * address.
+ */
+ addr = rounddown2(addr, 4);
+
+ /*
+ * Some control fields are ignored, and other bits reserved.
+ * Only unlinked, address-matching breakpoints are supported.
+ *
+ * XXX: fields that appear unvalidated, such as BAS, have
+ * constrained undefined behaviour. If the user mis-programs
+ * these, there is no risk to the system.
+ */
+ ctrl &= DBG_BCR_EN | DBG_BCR_PMC | DBG_BCR_BAS;
+ if ((ctrl & DBG_BCR_EN) != 0) {
+ /* Only target EL0. */
+ if ((ctrl & DBG_BCR_PMC) != DBG_BCR_PMC_EL0)
+ return (EINVAL);
+
monitor->dbg_enable_count++;
+ }
+
+ monitor->dbg_bvr[i] = addr;
+ monitor->dbg_bcr[i] = ctrl;
}
if (monitor->dbg_enable_count > 0)
monitor->dbg_flags |= DBGMON_ENABLED;
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index 201d7559320b..73d1010057b9 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -943,6 +943,23 @@
#define DBG_MDSCR_KDE (0x1 << 13)
#define DBG_MDSCR_MDE (0x1 << 15)
+/* Debug Breakpoint Control Registers */
+#define DBG_BCR_EN 0x1
+#define DBG_BCR_PMC_SHIFT 1
+#define DBG_BCR_PMC (0x3 << DBG_BCR_PMC_SHIFT)
+#define DBG_BCR_PMC_EL1 (0x1 << DBG_BCR_PMC_SHIFT)
+#define DBG_BCR_PMC_EL0 (0x2 << DBG_BCR_PMC_SHIFT)
+#define DBG_BCR_BAS_SHIFT 5
+#define DBG_BCR_BAS (0xf << DBG_BCR_BAS_SHIFT)
+#define DBG_BCR_HMC_SHIFT 13
+#define DBG_BCR_HMC (0x1 << DBG_BCR_HMC_SHIFT)
+#define DBG_BCR_SSC_SHIFT 14
+#define DBG_BCR_SSC (0x3 << DBG_BCR_SSC_SHIFT)
+#define DBG_BCR_LBN_SHIFT 16
+#define DBG_BCR_LBN (0xf << DBG_BCR_LBN_SHIFT)
+#define DBG_BCR_BT_SHIFT 20
+#define DBG_BCR_BT (0xf << DBG_BCR_BT_SHIFT)
+
/* Perfomance Monitoring Counters */
#define PMCR_E (1 << 0) /* Enable all counters */
#define PMCR_P (1 << 1) /* Reset all counters */
More information about the dev-commits-src-all
mailing list