According to the RISC-V smcdeleg specification: "When menvcfg.CDE=0,
attempts to access scountinhibit raise an illegal-instruction
exception."
The current implementation of scountinhibit_pred() only checks the
hardware extensions (ext_ssccfg, ext_smcdeleg) and virtualization
status, but completely misses the runtime environment configuration
check (menvcfg.CDE). This allows S-mode to access scountinhibit even
when the M-mode has explicitly disabled counter delegation.
This issue was discovered by the SpecHunter tool
(https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2571/qemu.txt).
Fixes: 6247dc2ef70b ("target/riscv: Add counter delegation/configuration support")
Signed-off-by: Zishun Yi <vulab@iscas.ac.cn>
---
target/riscv/csr.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index da366cf56271..8e494f545d76 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -17,6 +17,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "cpu_bits.h"
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/timer.h"
@@ -398,6 +399,10 @@ static RISCVException scountinhibit_pred(CPURISCVState *env, int csrno)
return RISCV_EXCP_ILLEGAL_INST;
}
+ if (!get_field(env->menvcfg, MENVCFG_CDE)) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
if (env->virt_enabled) {
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
}
--
2.51.2