ANDROID: arm64: only permit certain alternatives in the FIPS140 module

The FIPS140 crypto module takes a HMAC digest of its own .text and
.rodata section in its module_init() hook. This digest is compared to a
digest taken at build time, which means that we need to take some extra
care to ensure that the build time and runtime versions line up.

One thing we cannot tolerate in this case is alternatives patching. In
the general case, we cannot simply ignore alternatives, but fortunately,
there is only a small subset that actually gets instantiated in the
FIPS140 module, and all of these can be ignored if we are willing to
accept that the FIPS140 module does not support VHE hardware, and does
not work when running with pseudo-NMI support enabled. None of this is
important for the use case targeted by the FIPS140 module, so this is
something we should be able to live with.

Bug: 153614920
Bug: 188620248
Change-Id: Ie6666e01d5524a3c33aa451609bab2f29b612f8c
Signed-off-by: Ard Biesheuvel <ardb@google.com>
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
Ard Biesheuvel
2021-06-03 15:18:35 +00:00
committed by Matthias Männich
parent 6bfb9916dc
commit 059d29197b
@@ -19,6 +19,7 @@
#error "cpucaps have overflown ARM64_CB_BIT"
#endif
#ifndef BUILD_FIPS140_KO
#ifndef __ASSEMBLY__
#include <linux/stringify.h>
@@ -265,4 +266,60 @@ l_yes:
#endif /* __ASSEMBLY__ */
#else
/*
* The FIPS140 module does not support alternatives patching, as this
* invalidates the HMAC digest of the .text section. However, some alternatives
* are known to be irrelevant so we can tolerate them in the FIPS140 module, as
* they will never be applied in the first place in the use cases that the
* FIPS140 module targets (Android running on a production phone). Any other
* uses of alternatives should be avoided, as it is not safe in the general
* case to simply use the default sequence in one place (the fips module) and
* the alternative sequence everywhere else.
*
* Below is an allowlist of cpucaps that we can ignore, by simply taking the
* safe default instruction sequence. Note that this implies that the FIPS140
* module is not compatible with VHE, or with pseudo-NMI support.
*/
#define __ALT_ARM64_HAS_LDAPR 0,
#define __ALT_ARM64_HAS_VIRT_HOST_EXTN 0,
#define __ALT_ARM64_HAS_GIC_PRIO_MASKING 0,
#define __ALT_ARM64_HAS_GIC_PRIO_RELAXED_SYNC 0,
#define ALTERNATIVE(oldinstr, newinstr, cpucap, ...) \
_ALTERNATIVE(oldinstr, __ALT_ ## cpucap, #cpucap)
#define ALTERNATIVE_CB(oldinstr, cpucap, cb) \
_ALTERNATIVE(oldinstr, __ALT_ ## cpucap, #cpucap)
#define _ALTERNATIVE(oldinstr, cpucap, cpucap_str) \
__take_second_arg(cpucap oldinstr, \
".err CPU capability " cpucap_str " not supported in fips140 module")
#ifndef __ASSEMBLY__
#include <linux/types.h>
static bool cpus_have_cap(unsigned int num);
/*
* Return 'false' for all capabilities listed above, and use the slow path for
* the remaining ones. This ensures that the FIPS140 module is consistent with
* itself for all capabilities, and with the rest of the kernel at least for the
* ones not listed.
*/
#define __alternative_has_cap(cpucap, altcap) \
__take_second_arg(altcap false, cpus_have_cap(cpucap))
#define alternative_has_cap_likely(cpucap) \
__alternative_has_cap(cpucap, __ALT_ ## cpucap)
#define alternative_has_cap_unlikely alternative_has_cap_likely
#endif /* !__ASSEMBLY__ */
#endif /* BUILD_FIPS140_KO */
#endif /* __ASM_ALTERNATIVE_MACROS_H */