Flags are great, but flags can also be dangerous: it is easy to encode a flag that is bigger than its container (unless the container is a u64), and it is easy to construct a flag value that doesn't fit in the mask that is associated with it. Add a couple of build-time sanity checks that ensure we catch these two cases. Reviewed-by: Fuad Tabba <tabba@xxxxxxxxxx> Signed-off-by: Marc Zyngier <maz@xxxxxxxxxx> --- arch/arm64/include/asm/kvm_host.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index ffbeb5f5692e..6a37018f40b7 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -433,8 +433,20 @@ struct kvm_vcpu_arch { #define __unpack_flag(_set, _f, _m) _f #define unpack_vcpu_flag(...) __unpack_flag(__VA_ARGS__) +#define __build_check_flag(v, flagset, f, m) \ + do { \ + typeof(v->arch.flagset) *_fset; \ + \ + /* Check that the flags fit in the mask */ \ + BUILD_BUG_ON(HWEIGHT(m) != HWEIGHT((f) | (m))); \ + /* Check that the flags fit in the type */ \ + BUILD_BUG_ON((sizeof(*_fset) * 8) <= __fls(m)); \ + } while (0) + #define __vcpu_get_flag(v, flagset, f, m) \ ({ \ + __build_check_flag(v, flagset, f, m); \ + \ v->arch.flagset & (m); \ }) @@ -442,6 +454,8 @@ struct kvm_vcpu_arch { do { \ typeof(v->arch.flagset) *fset; \ \ + __build_check_flag(v, flagset, f, m); \ + \ fset = &v->arch.flagset; \ if (HWEIGHT(m) > 1) \ *fset &= ~(m); \ @@ -452,6 +466,8 @@ struct kvm_vcpu_arch { do { \ typeof(v->arch.flagset) *fset; \ \ + __build_check_flag(v, flagset, f, m); \ + \ fset = &v->arch.flagset; \ *fset &= ~(m); \ } while (0) -- 2.34.1 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm