diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2020-07-27 16:12:11 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-07-27 16:12:11 +0100 |
commit | d4f6dda182e19afa75706936805e18397cb95f07 (patch) | |
tree | f746b1fe7800e2de1bf339fd16c37656fdae7434 /target | |
parent | 7ad01d78a9f2e80d1be41226d98f34059f7fff90 (diff) | |
download | qemu-d4f6dda182e19afa75706936805e18397cb95f07.zip |
target/arm: Improve IMPDEF algorithm for IRG
When GCR_EL1.RRND==1, the choosing of the random value is IMPDEF,
and the kernel is not expected to have set RGSR_EL1. Force a
non-zero value into SEED, so that we do not continually return
the same tag.
Reported-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200724163853.504655-4-richard.henderson@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/mte_helper.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c index 5ea57d487a..104752041f 100644 --- a/target/arm/mte_helper.c +++ b/target/arm/mte_helper.c @@ -24,6 +24,8 @@ #include "exec/ram_addr.h" #include "exec/cpu_ldst.h" #include "exec/helper-proto.h" +#include "qapi/error.h" +#include "qemu/guest-random.h" static int choose_nonexcluded_tag(int tag, int offset, uint16_t exclude) @@ -211,16 +213,37 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, uint64_t HELPER(irg)(CPUARMState *env, uint64_t rn, uint64_t rm) { - int rtag; - - /* - * Our IMPDEF choice for GCR_EL1.RRND==1 is to behave as if - * GCR_EL1.RRND==0, always producing deterministic results. - */ uint16_t exclude = extract32(rm | env->cp15.gcr_el1, 0, 16); + int rrnd = extract32(env->cp15.gcr_el1, 16, 1); int start = extract32(env->cp15.rgsr_el1, 0, 4); int seed = extract32(env->cp15.rgsr_el1, 8, 16); - int offset, i; + int offset, i, rtag; + + /* + * Our IMPDEF choice for GCR_EL1.RRND==1 is to continue to use the + * deterministic algorithm. Except that with RRND==1 the kernel is + * not required to have set RGSR_EL1.SEED != 0, which is required for + * the deterministic algorithm to function. So we force a non-zero + * SEED for that case. + */ + if (unlikely(seed == 0) && rrnd) { + do { + Error *err = NULL; + uint16_t two; + + if (qemu_guest_getrandom(&two, sizeof(two), &err) < 0) { + /* + * Failed, for unknown reasons in the crypto subsystem. + * Best we can do is log the reason and use a constant seed. + */ + qemu_log_mask(LOG_UNIMP, "IRG: Crypto failure: %s\n", + error_get_pretty(err)); + error_free(err); + two = 1; + } + seed = two; + } while (seed == 0); + } /* RandomTag */ for (i = offset = 0; i < 4; ++i) { |