• Alice Ryhl's avatar
    cfi: encode cfi normalized integers + kasan/gcov bug in Kconfig · 4c66f830
    Alice Ryhl authored
    There is a bug in the LLVM implementation of KASAN and GCOV that makes
    these options incompatible with the CFI_ICALL_NORMALIZE_INTEGERS option.
    
    The bug has already been fixed in llvm/clang [1] and rustc [2]. However,
    Kconfig currently has no way to gate features on the LLVM version inside
    rustc, so we cannot write down a precise `depends on` clause in this
    case. Instead, a `def_bool` option is defined for whether
    CFI_ICALL_NORMALIZE_INTEGERS is available, and its default value is set
    to false when GCOV or KASAN are turned on. End users using a patched
    clang/rustc can turn on the HAVE_CFI_ICALL_NORMALIZE_INTEGERS option
    directly to override this.
    
    An alternative solution is to inspect a binary created by clang or rustc
    to see whether the faulty CFI tags are in the binary. This would be a
    precise check, but it would involve hard-coding the *hashed* version of
    the CFI tag. This is because there's no way to get clang or rustc to
    output the unhased version of the CFI tag. Relying on the precise
    hashing algorithm using by CFI seems too fragile, so I have not pursued
    this option. Besides, this kind of hack is exactly what lead to the LLVM
    bug in the first place.
    
    If the CFI_ICALL_NORMALIZE_INTEGERS option is used without CONFIG_RUST,
    then we actually can perform a precise check today: just compare the
    clang version number. This works since clang and llvm are always updated
    in lockstep. However, encoding this in Kconfig would give the
    HAVE_CFI_ICALL_NORMALIZE_INTEGERS option a dependency on CONFIG_RUST,
    which is not possible as the reverse dependency already exists.
    
    HAVE_CFI_ICALL_NORMALIZE_INTEGERS is defined to be a `def_bool` instead
    of `bool` to avoid asking end users whether they want to turn on the
    option. Turning it on explicitly is something only experts should do, so
    making it hard to do so is not an issue.
    
    I added a `depends on CFI_CLANG` clause to the new Kconfig option. I'm
    not sure whether that makes sense or not, but it doesn't seem to make a
    big difference.
    
    In a future kernel release, I would like to add a Kconfig option similar
    to CLANG_VERSION/RUSTC_VERSION for inspecting the version of the LLVM
    inside rustc. Once that feature lands, this logic will be replaced with
    a precise version check. This check is not being introduced here to
    avoid introducing a new _VERSION constant in a fix.
    
    Link: https://github.com/llvm/llvm-project/pull/104826 [1]
    Link: https://github.com/rust-lang/rust/pull/129373 [2]
    Fixes: ce4a2620 ("cfi: add CONFIG_CFI_ICALL_NORMALIZE_INTEGERS")
    Reported-by: default avatarkernel test robot <oliver.sang@intel.com>
    Closes: https://lore.kernel.org/oe-lkp/202409231044.4f064459-oliver.sang@intel.comSigned-off-by: default avatarAlice Ryhl <aliceryhl@google.com>
    Reviewed-by: default avatarSami Tolvanen <samitolvanen@google.com>
    Link: https://lore.kernel.org/r/20240925-cfi-norm-kasan-fix-v1-1-0328985cdf33@google.comSigned-off-by: default avatarMiguel Ojeda <ojeda@kernel.org>
    4c66f830
Kconfig 64.5 KB