Date: Wed, 24 Feb 2021 15:02:42 GMT From: Mitchell Horne <mhorne@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 8837e9c54072 - stable/13 - arm64: validate breakpoint registers Message-ID: <202102241502.11OF2gOw013440@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=8837e9c54072679b69ae0c0345e7ef7d241255aa commit 8837e9c54072679b69ae0c0345e7ef7d241255aa Author: Mitchell Horne <mhorne@FreeBSD.org> AuthorDate: 2021-02-09 18:29:38 +0000 Commit: Mitchell Horne <mhorne@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202102241502.11OF2gOw013440>