Skip to content

Commit d2a02e3

Browse files
committed
lib/crypto: blake2s: avoid indirect calls to compression function for Clang CFI
blake2s_compress_generic is weakly aliased by blake2s_compress. The current harness for function selection uses a function pointer, which is ordinarily inlined and resolved at compile time. But when Clang's CFI is enabled, CFI still triggers when making an indirect call via a weak symbol. This seems like a bug in Clang's CFI, as though it's bucketing weak symbols and strong symbols differently. It also only seems to trigger when "full LTO" mode is used, rather than "thin LTO". [ 0.000000][ T0] Kernel panic - not syncing: CFI failure (target: blake2s_compress_generic+0x0/0x1444) [ 0.000000][ T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.16.0-mainline-06981-g076c855b846e #1 [ 0.000000][ T0] Hardware name: MT6873 (DT) [ 0.000000][ T0] Call trace: [ 0.000000][ T0] dump_backtrace+0xfc/0x1dc [ 0.000000][ T0] dump_stack_lvl+0xa8/0x11c [ 0.000000][ T0] panic+0x194/0x464 [ 0.000000][ T0] __cfi_check_fail+0x54/0x58 [ 0.000000][ T0] __cfi_slowpath_diag+0x354/0x4b0 [ 0.000000][ T0] blake2s_update+0x14c/0x178 [ 0.000000][ T0] _extract_entropy+0xf4/0x29c [ 0.000000][ T0] crng_initialize_primary+0x24/0x94 [ 0.000000][ T0] rand_initialize+0x2c/0x6c [ 0.000000][ T0] start_kernel+0x2f8/0x65c [ 0.000000][ T0] __primary_switched+0xc4/0x7be4 [ 0.000000][ T0] Rebooting in 5 seconds.. Nonetheless, the function pointer method isn't so terrific anyway, so this patch replaces it with a simple boolean, which also gets inlined away. This successfully works around the Clang bug. In general, I'm not too keen on all of the indirection involved here; it clearly does more harm than good. Hopefully the whole thing can get cleaned up down the road when lib/crypto is overhauled more comprehensively. But for now, we go with a simple bandaid. Fixes: 6048fdc ("lib/crypto: blake2s: include as built-in") Link: ClangBuiltLinux#1567 Reported-by: Miles Chen <[email protected]> Tested-by: Miles Chen <[email protected]> Tested-by: Nathan Chancellor <[email protected]> Tested-by: John Stultz <[email protected]> Acked-by: Nick Desaulniers <[email protected]> Reviewed-by: Eric Biggers <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 26291c5 commit d2a02e3

File tree

5 files changed

+33
-23
lines changed

5 files changed

+33
-23
lines changed

arch/arm/crypto/blake2s-shash.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
static int crypto_blake2s_update_arm(struct shash_desc *desc,
1414
const u8 *in, unsigned int inlen)
1515
{
16-
return crypto_blake2s_update(desc, in, inlen, blake2s_compress);
16+
return crypto_blake2s_update(desc, in, inlen, false);
1717
}
1818

1919
static int crypto_blake2s_final_arm(struct shash_desc *desc, u8 *out)
2020
{
21-
return crypto_blake2s_final(desc, out, blake2s_compress);
21+
return crypto_blake2s_final(desc, out, false);
2222
}
2323

2424
#define BLAKE2S_ALG(name, driver_name, digest_size) \

arch/x86/crypto/blake2s-shash.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
static int crypto_blake2s_update_x86(struct shash_desc *desc,
1919
const u8 *in, unsigned int inlen)
2020
{
21-
return crypto_blake2s_update(desc, in, inlen, blake2s_compress);
21+
return crypto_blake2s_update(desc, in, inlen, false);
2222
}
2323

2424
static int crypto_blake2s_final_x86(struct shash_desc *desc, u8 *out)
2525
{
26-
return crypto_blake2s_final(desc, out, blake2s_compress);
26+
return crypto_blake2s_final(desc, out, false);
2727
}
2828

2929
#define BLAKE2S_ALG(name, driver_name, digest_size) \

crypto/blake2s_generic.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
static int crypto_blake2s_update_generic(struct shash_desc *desc,
1616
const u8 *in, unsigned int inlen)
1717
{
18-
return crypto_blake2s_update(desc, in, inlen, blake2s_compress_generic);
18+
return crypto_blake2s_update(desc, in, inlen, true);
1919
}
2020

2121
static int crypto_blake2s_final_generic(struct shash_desc *desc, u8 *out)
2222
{
23-
return crypto_blake2s_final(desc, out, blake2s_compress_generic);
23+
return crypto_blake2s_final(desc, out, true);
2424
}
2525

2626
#define BLAKE2S_ALG(name, driver_name, digest_size) \

include/crypto/internal/blake2s.h

+25-15
Original file line numberDiff line numberDiff line change
@@ -24,44 +24,54 @@ static inline void blake2s_set_lastblock(struct blake2s_state *state)
2424
state->f[0] = -1;
2525
}
2626

27-
typedef void (*blake2s_compress_t)(struct blake2s_state *state,
28-
const u8 *block, size_t nblocks, u32 inc);
29-
3027
/* Helper functions for BLAKE2s shared by the library and shash APIs */
3128

32-
static inline void __blake2s_update(struct blake2s_state *state,
33-
const u8 *in, size_t inlen,
34-
blake2s_compress_t compress)
29+
static __always_inline void
30+
__blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen,
31+
bool force_generic)
3532
{
3633
const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen;
3734

3835
if (unlikely(!inlen))
3936
return;
4037
if (inlen > fill) {
4138
memcpy(state->buf + state->buflen, in, fill);
42-
(*compress)(state, state->buf, 1, BLAKE2S_BLOCK_SIZE);
39+
if (force_generic)
40+
blake2s_compress_generic(state, state->buf, 1,
41+
BLAKE2S_BLOCK_SIZE);
42+
else
43+
blake2s_compress(state, state->buf, 1,
44+
BLAKE2S_BLOCK_SIZE);
4345
state->buflen = 0;
4446
in += fill;
4547
inlen -= fill;
4648
}
4749
if (inlen > BLAKE2S_BLOCK_SIZE) {
4850
const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE);
4951
/* Hash one less (full) block than strictly possible */
50-
(*compress)(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE);
52+
if (force_generic)
53+
blake2s_compress_generic(state, in, nblocks - 1,
54+
BLAKE2S_BLOCK_SIZE);
55+
else
56+
blake2s_compress(state, in, nblocks - 1,
57+
BLAKE2S_BLOCK_SIZE);
5158
in += BLAKE2S_BLOCK_SIZE * (nblocks - 1);
5259
inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1);
5360
}
5461
memcpy(state->buf + state->buflen, in, inlen);
5562
state->buflen += inlen;
5663
}
5764

58-
static inline void __blake2s_final(struct blake2s_state *state, u8 *out,
59-
blake2s_compress_t compress)
65+
static __always_inline void
66+
__blake2s_final(struct blake2s_state *state, u8 *out, bool force_generic)
6067
{
6168
blake2s_set_lastblock(state);
6269
memset(state->buf + state->buflen, 0,
6370
BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */
64-
(*compress)(state, state->buf, 1, state->buflen);
71+
if (force_generic)
72+
blake2s_compress_generic(state, state->buf, 1, state->buflen);
73+
else
74+
blake2s_compress(state, state->buf, 1, state->buflen);
6575
cpu_to_le32_array(state->h, ARRAY_SIZE(state->h));
6676
memcpy(out, state->h, state->outlen);
6777
}
@@ -99,20 +109,20 @@ static inline int crypto_blake2s_init(struct shash_desc *desc)
99109

100110
static inline int crypto_blake2s_update(struct shash_desc *desc,
101111
const u8 *in, unsigned int inlen,
102-
blake2s_compress_t compress)
112+
bool force_generic)
103113
{
104114
struct blake2s_state *state = shash_desc_ctx(desc);
105115

106-
__blake2s_update(state, in, inlen, compress);
116+
__blake2s_update(state, in, inlen, force_generic);
107117
return 0;
108118
}
109119

110120
static inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out,
111-
blake2s_compress_t compress)
121+
bool force_generic)
112122
{
113123
struct blake2s_state *state = shash_desc_ctx(desc);
114124

115-
__blake2s_final(state, out, compress);
125+
__blake2s_final(state, out, force_generic);
116126
return 0;
117127
}
118128

lib/crypto/blake2s.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818

1919
void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen)
2020
{
21-
__blake2s_update(state, in, inlen, blake2s_compress);
21+
__blake2s_update(state, in, inlen, false);
2222
}
2323
EXPORT_SYMBOL(blake2s_update);
2424

2525
void blake2s_final(struct blake2s_state *state, u8 *out)
2626
{
2727
WARN_ON(IS_ENABLED(DEBUG) && !out);
28-
__blake2s_final(state, out, blake2s_compress);
28+
__blake2s_final(state, out, false);
2929
memzero_explicit(state, sizeof(*state));
3030
}
3131
EXPORT_SYMBOL(blake2s_final);

0 commit comments

Comments
 (0)