The branch stable/13 has been updated by mhorne:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8837e9c54072679b69ae0c0345e7ef7d241255aa

commit 8837e9c54072679b69ae0c0345e7ef7d241255aa
Author:     Mitchell Horne <mho...@freebsd.org>
AuthorDate: 2021-02-09 18:29:38 +0000
Commit:     Mitchell Horne <mho...@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 */
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to