From: George Popescu <georgep...@google.com> Whenever an arithmetic overflow: addition, substraction, multiplication, division or negating happens inside the hyp/nVHE code, an __ubsan_handle_*_overflow is called.
All the overflow handlers are sharing the same structure called overflow_data. Signed-off-by: George Popescu <georgep...@google.com> Change-Id: Iec1ef331e471efbb35a39ffaee0641107a3a0e3a Signed-off-by: Elena Petrova <lena...@google.com> --- arch/arm64/include/asm/kvm_ubsan.h | 10 ++++++-- arch/arm64/kvm/hyp/nvhe/ubsan.c | 40 ++++++++++++++++++++++++++---- arch/arm64/kvm/kvm_ubsan_buffer.c | 20 ++++++++++++++- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/kvm_ubsan.h b/arch/arm64/include/asm/kvm_ubsan.h index 93c1b695097a..da4a3b4e28e0 100644 --- a/arch/arm64/include/asm/kvm_ubsan.h +++ b/arch/arm64/include/asm/kvm_ubsan.h @@ -22,7 +22,8 @@ struct kvm_ubsan_info { UBSAN_UNREACHABLE_DATA, UBSAN_SHIFT_OUT_OF_BOUNDS, UBSAN_INVALID_DATA, - UBSAN_TYPE_MISMATCH + UBSAN_TYPE_MISMATCH, + UBSAN_OVERFLOW_DATA } type; union { struct out_of_bounds_data out_of_bounds_data; @@ -30,6 +31,7 @@ struct kvm_ubsan_info { struct shift_out_of_bounds_data shift_out_of_bounds_data; struct invalid_value_data invalid_value_data; struct type_mismatch_data type_mismatch_data; + struct overflow_data overflow_data; }; union { struct ubsan_values u_val; @@ -41,4 +43,8 @@ void __ubsan_handle_builtin_unreachable(void *_data); void __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs); void __ubsan_handle_load_invalid_value(void *_data, void *val); void __ubsan_handle_type_mismatch(struct type_mismatch_data *_data, void *ptr); - +void __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs); +void __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs); +void __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs); +void __ubsan_handle_negate_overflow(void *_data, void *old_val); +void __ubsan_handle_divrem_overflow(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 a9f72d4bcab7..f16842ff7316 100644 --- a/arch/arm64/kvm/hyp/nvhe/ubsan.c +++ b/arch/arm64/kvm/hyp/nvhe/ubsan.c @@ -47,15 +47,45 @@ static void write_type_mismatch_data(struct type_mismatch_data_common *data, voi } } -void __ubsan_handle_add_overflow(void *_data, void *lhs, void *rhs) {} +static void write_overflow_data(struct overflow_data *data, void *lval, void *rval, char op) +{ + struct kvm_ubsan_info *slot = kvm_ubsan_buffer_next_slot(); + + if (slot) { + slot->type = UBSAN_OVERFLOW_DATA; + slot->overflow_data = *data; + slot->u_val.op = op; + slot->u_val.lval = lval; + if (op != '!') + slot->u_val.rval = rval; + } +} + +void __ubsan_handle_add_overflow(void *_data, void *lhs, void *rhs) +{ + write_overflow_data(_data, lhs, rhs, '+'); +} -void __ubsan_handle_sub_overflow(void *_data, void *lhs, void *rhs) {} +void __ubsan_handle_sub_overflow(void *_data, void *lhs, void *rhs) +{ + write_overflow_data(_data, lhs, rhs, '-'); +} -void __ubsan_handle_mul_overflow(void *_data, void *lhs, void *rhs) {} +void __ubsan_handle_mul_overflow(void *_data, void *lhs, void *rhs) +{ + write_overflow_data(_data, lhs, rhs, '*'); +} -void __ubsan_handle_negate_overflow(void *_data, void *old_val) {} +void __ubsan_handle_negate_overflow(void *_data, void *old_val) +{ + write_overflow_data(_data, old_val, NULL, '!'); +} + +void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs) +{ + write_overflow_data(_data, lhs, rhs, '/'); +} -void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs) {} void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr) { diff --git a/arch/arm64/kvm/kvm_ubsan_buffer.c b/arch/arm64/kvm/kvm_ubsan_buffer.c index b7823dedf8b1..2c7060cbb48b 100644 --- a/arch/arm64/kvm/kvm_ubsan_buffer.c +++ b/arch/arm64/kvm/kvm_ubsan_buffer.c @@ -39,7 +39,25 @@ void __kvm_check_ubsan_data(struct kvm_ubsan_info *slot) __ubsan_handle_type_mismatch(&slot->type_mismatch_data, slot->u_val.lval); break; - } + case UBSAN_OVERFLOW_DATA: + if (slot->u_val.op == '/') { + __ubsan_handle_divrem_overflow(&slot->overflow_data, + slot->u_val.lval, slot->u_val.rval); + } else if (slot->u_val.op == '!') { + __ubsan_handle_negate_overflow(&slot->overflow_data, + slot->u_val.lval); + } else if (slot->u_val.op == '+') { + __ubsan_handle_add_overflow(&slot->overflow_data, + slot->u_val.lval, slot->u_val.rval); + } else if (slot->u_val.op == '-') { + __ubsan_handle_sub_overflow(&slot->overflow_data, + slot->u_val.lval, slot->u_val.rval); + } else if (slot->u_val.op == '*') { + __ubsan_handle_mul_overflow(&slot->overflow_data, + slot->u_val.lval, slot->u_val.rval); + } + break; + } } void iterate_kvm_ubsan_buffer(unsigned long left, unsigned long right) -- 2.30.0.284.gd98b1dd5eaa7-goog _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm