[PATCH 09/14] KVM: arm64: Enable shift out of bounds undefined behaviour check for hyp/nVHE

George-Aurelian Popescu
2020-09-14T17:32:41Z

From: George Popescu <georgepope@google.com>

__ubsan_handle_shift_out_of_bounds data is passed to the buffer inside
hyp/nVHE. This data is passed to the original handler from kernel.

The values of the operands of the shift expression are stored as the lhs
and rhs pointers, so there is no need to dereference them.

Signed-off-by: George Popescu <georgepope@google.com>
---
arch/arm64/include/asm/kvm_ubsan.h | 5 ++++-
arch/arm64/kvm/hyp/nvhe/ubsan.c | 14 +++++++++++++-
arch/arm64/kvm/kvm_ubsan_buffer.c | 4 ++++
3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_ubsan.h b/arch/arm64/include/asm/kvm_ubsan.h
index 7fd0d0dfbd82..3130a80cd8b2 100644
--- a/arch/arm64/include/asm/kvm_ubsan.h
+++ b/arch/arm64/include/asm/kvm_ubsan.h
@@ -21,11 +21,13 @@ struct kvm_ubsan_info {
enum {
UBSAN_NONE,
UBSAN_OUT_OF_BOUNDS,
- UBSAN_UNREACHABLE_DATA
+ UBSAN_UNREACHABLE_DATA,
+ UBSAN_SHIFT_OUT_OF_BOUNDS
} type;
union {
struct out_of_bounds_data out_of_bounds_data;
struct unreachable_data unreachable_data;
+ struct shift_out_of_bounds_data shift_out_of_bounds_data;
};
union {
struct ubsan_values u_val;
@@ -35,3 +37,4 @@ struct kvm_ubsan_info {

void __ubsan_handle_out_of_bounds(void *_data, void *index);
void __ubsan_handle_builtin_unreachable(void *_data);
+void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs);
diff --git a/arch/arm64/kvm/hyp/nvhe/ubsan.c b/arch/arm64/kvm/hyp/nvhe/ubsan.c
index 9497e7f7f397..40b82143e57f 100644
--- a/arch/arm64/kvm/hyp/nvhe/ubsan.c
+++ b/arch/arm64/kvm/hyp/nvhe/ubsan.c
@@ -56,7 +56,19 @@ void __ubsan_handle_out_of_bounds(void *_data, void *index)
}
}

-void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs) {}
+void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs)
+{
+ struct kvm_ubsan_info *slot;
+ struct shift_out_of_bounds_data *data = _data;
+
+ slot = kvm_ubsan_buffer_next_slot();
+ if (slot) {
+ slot->type = UBSAN_SHIFT_OUT_OF_BOUNDS;
+ slot->shift_out_of_bounds_data = *data;
+ slot->u_val.lval = lhs;
+ slot->u_val.rval = rhs;
+ }
+}

void __ubsan_handle_builtin_unreachable(void *_data)
{
diff --git a/arch/arm64/kvm/kvm_ubsan_buffer.c b/arch/arm64/kvm/kvm_ubsan_buffer.c
index f66cc5f7878e..b4a282bec91d 100644
--- a/arch/arm64/kvm/kvm_ubsan_buffer.c
+++ b/arch/arm64/kvm/kvm_ubsan_buffer.c
@@ -28,6 +28,10 @@ void __kvm_check_ubsan_data(struct kvm_ubsan_info *slot)
case UBSAN_UNREACHABLE_DATA:
__ubsan_handle_builtin_unreachable(&slot->unreachable_data);
break;
+ case UBSAN_SHIFT_OUT_OF_BOUNDS:
+ __ubsan_handle_shift_out_of_bounds(&slot->shift_out_of_bounds_data,
+ slot->u_val.lval, slot->u_val.rval);
+ break;
}
}

--
2.28.0.618.gf4bc123cb7-goog