diff --git a/sys/dev/raid/mpr/mpr_user.c b/sys/dev/raid/mpr/mpr_user.c index 767a4a1a..711f3641 100644 --- a/sys/dev/raid/mpr/mpr_user.c +++ b/sys/dev/raid/mpr/mpr_user.c @@ -2178,6 +2178,21 @@ static int mpr_user_reg_access(struct mpr_softc *sc, mpr_reg_access_t *data) { int status = 0; + u_long regs_size; + + /* + * DF-4020 (twin of DF-4012 on mps): RegOffset arrives straight from + * userspace (u32, mpr_ioctl.h:343) and was previously passed + * unvalidated into mpr_regread()/mpr_regwrite(), which are plain + * volatile loads/stores at bhandle+offset on the x86_64 memory bus + * space (mprvar.h:496-506). A member of group operator could thus + * read and write any kernel memory in the 4 GiB window above the + * register BAR (and panic the kernel on unmapped offsets). Bound + * the offset by the actual size of the mapped register aperture. + */ + regs_size = rman_get_size(sc->mpr_regs_resource); + if (data->RegOffset >= regs_size) + return (EINVAL); switch (data->Command) { /*