From 4b7d9a6af08cb704ce77eadba2a7bb1b06c1554c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 16 Jan 2024 13:24:29 +0000 Subject: [libc] Replace linker_assert() with build_assert() We currently implement build-time assertions via a mechanism that generates a call to an undefined external function that will cause the link to fail unless the compiler can prove that the asserted condition is true (and thereby eliminate the undefined function call). This assertion mechanism can be used for conditions that are not amenable to the use of static_assert(), since static_assert() will not allow for proofs via dead code elimination. Add __attribute__((error(...))) to the undefined external function, so that the error is raised at compile time rather than at link time. This allows us to provide a more meaningful error message (which will include the file name and line number, as with any other compile-time error), and avoids the need for the caller to specify a unique symbol name for the external function. Change the name from linker_assert() to build_assert(), since the assertion now takes place at compile time rather than at link time. Signed-off-by: Michael Brown --- src/include/ipxe/gcm.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/include/ipxe/gcm.h') diff --git a/src/include/ipxe/gcm.h b/src/include/ipxe/gcm.h index 90ef0b52..9653a0a1 100644 --- a/src/include/ipxe/gcm.h +++ b/src/include/ipxe/gcm.h @@ -88,13 +88,10 @@ struct _gcm_name ## _context { \ static int _gcm_name ## _setkey ( void *ctx, const void *key, \ size_t keylen ) { \ struct _gcm_name ## _context *context = ctx; \ - linker_assert ( _blocksize == sizeof ( context->gcm.key ), \ - _gcm_name ## _unsupported_blocksize ); \ - linker_assert ( ( ( void * ) &context->gcm ) == ctx, \ - _gcm_name ## _context_layout_error ); \ - linker_assert ( ( ( void * ) &context->raw ) == \ - ( ( void * ) context->gcm.raw_ctx ), \ - _gcm_name ## _context_layout_error ); \ + build_assert ( _blocksize == sizeof ( context->gcm.key ) ); \ + build_assert ( ( ( void * ) &context->gcm ) == ctx ); \ + build_assert ( ( ( void * ) &context->raw ) == \ + ( ( void * ) context->gcm.raw_ctx ) ); \ return gcm_setkey ( &context->gcm, key, keylen, &_raw_cipher ); \ } \ static void _gcm_name ## _setiv ( void *ctx, const void *iv, \ -- cgit v1.2.3-55-g7522 From 94b39fbe9298160b034c93ca06deb39a907e3b3f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 10 Feb 2024 14:41:29 +0000 Subject: [build] Fix build failures with older versions of gcc Some versions of gcc (observed with gcc 4.8.5 in CentOS 7) will report spurious build_assert() failures for some assertions about structure layouts. There is no clear pattern as to what causes these spurious failures, and the build assertion does succeed in that no unresolvable symbol reference is generated in the compiled code. Adjust the assertions to work around these apparent compiler issues. Signed-off-by: Michael Brown --- src/crypto/gcm.c | 14 ++++++++------ src/include/ipxe/gcm.h | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'src/include/ipxe/gcm.h') diff --git a/src/crypto/gcm.c b/src/crypto/gcm.c index c21aad14..a32890d5 100644 --- a/src/crypto/gcm.c +++ b/src/crypto/gcm.c @@ -469,13 +469,15 @@ int gcm_setkey ( struct gcm_context *context, const void *key, size_t keylen, * @v ivlen Initialisation vector length */ void gcm_setiv ( struct gcm_context *context, const void *iv, size_t ivlen ) { - union gcm_block *check = ( ( void * ) context ); - /* Sanity checks */ - build_assert ( &context->hash == check ); - build_assert ( &context->len == check + 1 ); - build_assert ( &context->ctr == check + 2 ); - build_assert ( &context->key == check + 3 ); + /* Sanity check: ensure that memset()s will clear expected state */ + build_assert ( &context->hash < &context->ctr ); + build_assert ( &context->len < &context->ctr ); + build_assert ( &context->ctr < &context->key ); + build_assert ( ( ( void * ) &context->raw_cipher ) > + ( ( void * ) &context->key ) ); + build_assert ( ( ( void * ) context->raw_ctx ) > + ( ( void * ) &context->key ) ); /* Reset non-key state */ memset ( context, 0, offsetof ( typeof ( *context ), key ) ); diff --git a/src/include/ipxe/gcm.h b/src/include/ipxe/gcm.h index 9653a0a1..4864445d 100644 --- a/src/include/ipxe/gcm.h +++ b/src/include/ipxe/gcm.h @@ -89,7 +89,8 @@ static int _gcm_name ## _setkey ( void *ctx, const void *key, \ size_t keylen ) { \ struct _gcm_name ## _context *context = ctx; \ build_assert ( _blocksize == sizeof ( context->gcm.key ) ); \ - build_assert ( ( ( void * ) &context->gcm ) == ctx ); \ + build_assert ( ( ( void * ) &context->gcm ) == \ + ( ( void * ) context ) ); \ build_assert ( ( ( void * ) &context->raw ) == \ ( ( void * ) context->gcm.raw_ctx ) ); \ return gcm_setkey ( &context->gcm, key, keylen, &_raw_cipher ); \ -- cgit v1.2.3-55-g7522