From a9ad113df005b4ecd7b719736c228b1da69aa8d6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 19 May 2020 23:38:32 -0700 Subject: fdtdec: Fix the types of addr and size in fdtdec_add_reserved_memory() fdtdec_get_addr_size() expects size is of type 'fdt_size_t', and return value is of type 'fdt_addr_t'. Adjust their types accordingly. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- lib/fdtdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 1f2b763acc3..42f7a255056 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1294,7 +1294,8 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, /* find a matching node and return the phandle to that */ fdt_for_each_subnode(node, blob, parent) { const char *name = fdt_get_name(blob, node, NULL); - phys_addr_t addr, size; + fdt_addr_t addr; + fdt_size_t size; addr = fdtdec_get_addr_size(blob, node, "reg", &size); if (addr == FDT_ADDR_T_NONE) { -- cgit v1.3.1 From f6704c79946c15fe327ff44e50f9559cd559d7ef Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 19 May 2020 23:38:33 -0700 Subject: fdtdec: Honor #address-cells and #size-cells in fdtdec_add_reserved_memory() At present fdtdec_add_reserved_memory() calls fdtdec_get_addr_size() to get address and size for the subnodes of /reserved-memory node. We should honor #address-cells and #size-cells properties in the parent node. Signed-off-by: Bin Meng Reviewed-by: Simon Glass --- lib/fdtdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 42f7a255056..0dd7ff1ac3f 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1297,7 +1297,8 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, fdt_addr_t addr; fdt_size_t size; - addr = fdtdec_get_addr_size(blob, node, "reg", &size); + addr = fdtdec_get_addr_size_fixed(blob, node, "reg", 0, na, ns, + &size, false); if (addr == FDT_ADDR_T_NONE) { debug("failed to read address/size for %s\n", name); continue; -- cgit v1.3.1 From d16b38f42704fe3cc94fbee1601be96045013151 Mon Sep 17 00:00:00 2001 From: Reuben Dowle Date: Thu, 16 Apr 2020 17:36:52 +1200 Subject: Add support for SHA384 and SHA512 The current recommendation for best security practice from the US government is to use SHA384 for TOP SECRET [1]. This patch adds support for SHA384 and SHA512 in the hash command, and also allows FIT images to be hashed with these algorithms, and signed with sha384,rsaXXXX and sha512,rsaXXXX The SHA implementation is adapted from the linux kernel implementation. [1] Commercial National Security Algorithm Suite http://www.iad.gov/iad/programs/iad-initiatives/cnsa-suite.cfm Signed-off-by: Reuben Dowle --- Kconfig | 26 ++- common/hash.c | 85 +++++++++- common/image-fit.c | 9 + common/image-sig.c | 26 ++- common/spl/Kconfig | 32 +++- include/hash.h | 4 + include/image.h | 18 ++ include/u-boot/rsa-checksum.h | 1 + include/u-boot/sha512.h | 38 +++++ lib/Kconfig | 23 +++ lib/Makefile | 1 + lib/sha512.c | 383 ++++++++++++++++++++++++++++++++++++++++++ tools/Makefile | 2 + 13 files changed, 632 insertions(+), 16 deletions(-) create mode 100644 include/u-boot/sha512.h create mode 100644 lib/sha512.c (limited to 'lib') diff --git a/Kconfig b/Kconfig index 0e7ccc0b074..34a88ebe348 100644 --- a/Kconfig +++ b/Kconfig @@ -358,12 +358,26 @@ config FIT_ENABLE_SHA256_SUPPORT help Enable this to support SHA256 checksum of FIT image contents. A SHA256 checksum is a 256-bit (32-byte) hash value used to check that - the image contents have not been corrupted. SHA256 is recommended - for use in secure applications since (as at 2016) there is no known - feasible attack that could produce a 'collision' with differing - input data. Use this for the highest security. Note that only the - SHA256 variant is supported: SHA512 and others are not currently - supported in U-Boot. + the image contents have not been corrupted. + +config FIT_ENABLE_SHA384_SUPPORT + bool "Support SHA384 checksum of FIT image contents" + default n + select SHA384 + help + Enable this to support SHA384 checksum of FIT image contents. A + SHA384 checksum is a 384-bit (48-byte) hash value used to check that + the image contents have not been corrupted. Use this for the highest + security. + +config FIT_ENABLE_SHA512_SUPPORT + bool "Support SHA512 checksum of FIT image contents" + default n + select SHA512 + help + Enable this to support SHA512 checksum of FIT image contents. A + SHA512 checksum is a 512-bit (64-byte) hash value used to check that + the image contents have not been corrupted. config FIT_SIGNATURE bool "Enable signature verification of FIT uImages" diff --git a/common/hash.c b/common/hash.c index 8c00659d252..5c75848b7d9 100644 --- a/common/hash.c +++ b/common/hash.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #if !defined(USE_HOSTCC) && defined(CONFIG_NEEDS_MANUAL_RELOC) @@ -95,6 +96,65 @@ static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void } #endif +#if defined(CONFIG_SHA384) +static int hash_init_sha384(struct hash_algo *algo, void **ctxp) +{ + sha512_context *ctx = malloc(sizeof(sha512_context)); + sha384_starts(ctx); + *ctxp = ctx; + return 0; +} + +static int hash_update_sha384(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, int is_last) +{ + sha384_update((sha512_context *)ctx, buf, size); + return 0; +} + +static int hash_finish_sha384(struct hash_algo *algo, void *ctx, void + *dest_buf, int size) +{ + if (size < algo->digest_size) + return -1; + + sha384_finish((sha512_context *)ctx, dest_buf); + free(ctx); + return 0; +} +#endif + +#if defined(CONFIG_SHA512) +static int hash_init_sha512(struct hash_algo *algo, void **ctxp) +{ + sha512_context *ctx = malloc(sizeof(sha512_context)); + sha512_starts(ctx); + *ctxp = ctx; + return 0; +} + +static int hash_update_sha512(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, int is_last) +{ + sha512_update((sha512_context *)ctx, buf, size); + return 0; +} + +static int hash_finish_sha512(struct hash_algo *algo, void *ctx, void + *dest_buf, int size) +{ + if (size < algo->digest_size) + return -1; + + printf("hello world\n"); + + sha512_finish((sha512_context *)ctx, dest_buf); + free(ctx); + return 0; +} +#endif + + static int hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp) { uint16_t *ctx = malloc(sizeof(uint16_t)); @@ -195,6 +255,28 @@ static struct hash_algo hash_algo[] = { .hash_finish = hash_finish_sha256, #endif }, +#endif +#ifdef CONFIG_SHA384 + { + .name = "sha384", + .digest_size = SHA384_SUM_LEN, + .chunk_size = CHUNKSZ_SHA384, + .hash_func_ws = sha384_csum_wd, + .hash_init = hash_init_sha384, + .hash_update = hash_update_sha384, + .hash_finish = hash_finish_sha384, + }, +#endif +#ifdef CONFIG_SHA512 + { + .name = "sha512", + .digest_size = SHA512_SUM_LEN, + .chunk_size = CHUNKSZ_SHA512, + .hash_func_ws = sha512_csum_wd, + .hash_init = hash_init_sha512, + .hash_update = hash_update_sha512, + .hash_finish = hash_finish_sha512, + }, #endif { .name = "crc16-ccitt", @@ -218,7 +300,8 @@ static struct hash_algo hash_algo[] = { /* Try to minimize code size for boards that don't want much hashing */ #if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) || \ - defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) + defined(CONFIG_CRC32_VERIFY) || defined(CONFIG_CMD_HASH) || \ + defined(CONFIG_SHA384) || defined(CONFIG_SHA512) #define multi_hash() 1 #else #define multi_hash() 0 diff --git a/common/image-fit.c b/common/image-fit.c index 1ece100a214..d54eff9033c 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR; #include #include #include +#include /*****************************************************************************/ /* New uImage format routines */ @@ -1206,6 +1207,14 @@ int calculate_hash(const void *data, int data_len, const char *algo, sha256_csum_wd((unsigned char *)data, data_len, (unsigned char *)value, CHUNKSZ_SHA256); *value_len = SHA256_SUM_LEN; + } else if (IMAGE_ENABLE_SHA384 && strcmp(algo, "sha384") == 0) { + sha384_csum_wd((unsigned char *)data, data_len, + (unsigned char *)value, CHUNKSZ_SHA384); + *value_len = SHA384_SUM_LEN; + } else if (IMAGE_ENABLE_SHA512 && strcmp(algo, "sha512") == 0) { + sha512_csum_wd((unsigned char *)data, data_len, + (unsigned char *)value, CHUNKSZ_SHA512); + *value_len = SHA512_SUM_LEN; } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) { md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5); *value_len = 16; diff --git a/common/image-sig.c b/common/image-sig.c index 498969d6414..f3c209ae8b7 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -40,7 +40,31 @@ struct checksum_algo checksum_algos[] = { .calculate_sign = EVP_sha256, #endif .calculate = hash_calculate, - } + }, +#ifdef CONFIG_SHA384 + { + .name = "sha384", + .checksum_len = SHA384_SUM_LEN, + .der_len = SHA384_DER_LEN, + .der_prefix = sha384_der_prefix, +#if IMAGE_ENABLE_SIGN + .calculate_sign = EVP_sha384, +#endif + .calculate = hash_calculate, + }, +#endif +#ifdef CONFIG_SHA512 + { + .name = "sha512", + .checksum_len = SHA512_SUM_LEN, + .der_len = SHA512_DER_LEN, + .der_prefix = sha512_der_prefix, +#if IMAGE_ENABLE_SIGN + .calculate_sign = EVP_sha512, +#endif + .calculate = hash_calculate, + }, +#endif }; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 8ece9057b1e..3eae65ebc19 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -412,7 +412,7 @@ config SPL_MD5_SUPPORT secure as it is possible (with a brute-force attack) to adjust the image while still retaining the same MD5 hash value. For secure applications where images may be changed maliciously, you should - consider SHA1 or SHA256. + consider SHA256 or SHA384. config SPL_SHA1_SUPPORT bool "Support SHA1" @@ -424,7 +424,7 @@ config SPL_SHA1_SUPPORT image contents have not been corrupted or maliciously altered. While SHA1 is fairly secure it is coming to the end of its life due to the expanding computing power available to brute-force - attacks. For more security, consider SHA256. + attacks. For more security, consider SHA256 or SHA384. config SPL_SHA256_SUPPORT bool "Support SHA256" @@ -433,12 +433,28 @@ config SPL_SHA256_SUPPORT help Enable this to support SHA256 in FIT images within SPL. A SHA256 checksum is a 256-bit (32-byte) hash value used to check that the - image contents have not been corrupted. SHA256 is recommended for - use in secure applications since (as at 2016) there is no known - feasible attack that could produce a 'collision' with differing - input data. Use this for the highest security. Note that only the - SHA256 variant is supported: SHA512 and others are not currently - supported in U-Boot. + image contents have not been corrupted. + +config SPL_SHA384_SUPPORT + bool "Support SHA384" + depends on SPL_FIT + select SHA384 + select SHA512_ALGO + help + Enable this to support SHA384 in FIT images within SPL. A SHA384 + checksum is a 384-bit (48-byte) hash value used to check that the + image contents have not been corrupted. Use this for the highest + security. + +config SPL_SHA512_SUPPORT + bool "Support SHA512" + depends on SPL_FIT + select SHA512 + select SHA512_ALGO + help + Enable this to support SHA512 in FIT images within SPL. A SHA512 + checksum is a 512-bit (64-byte) hash value used to check that the + image contents have not been corrupted. config SPL_FIT_IMAGE_TINY bool "Remove functionality from SPL FIT loading to reduce size" diff --git a/include/hash.h b/include/hash.h index 835962e7f66..97bb3ed5d9a 100644 --- a/include/hash.h +++ b/include/hash.h @@ -12,7 +12,11 @@ struct cmd_tbl; * Maximum digest size for all algorithms we support. Having this value * avoids a malloc() or C99 local declaration in common/cmd_hash.c. */ +#if defined(CONFIG_SHA384) || defined(CONFIG_SHA512) +#define HASH_MAX_DIGEST_SIZE 64 +#else #define HASH_MAX_DIGEST_SIZE 32 +#endif enum { HASH_FLAG_VERIFY = 1 << 0, /* Enable verify mode */ diff --git a/include/image.h b/include/image.h index ad81dad4442..ebd581a5944 100644 --- a/include/image.h +++ b/include/image.h @@ -32,8 +32,12 @@ struct fdt_region; #define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ #define CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT 1 #define CONFIG_FIT_ENABLE_SHA256_SUPPORT +#define CONFIG_FIT_ENABLE_SHA384_SUPPORT +#define CONFIG_FIT_ENABLE_SHA512_SUPPORT #define CONFIG_SHA1 #define CONFIG_SHA256 +#define CONFIG_SHA384 +#define CONFIG_SHA512 #define IMAGE_ENABLE_IGNORE 0 #define IMAGE_INDENT_STRING "" @@ -92,6 +96,20 @@ struct fdt_region; #define IMAGE_ENABLE_SHA256 0 #endif +#if defined(CONFIG_FIT_ENABLE_SHA384_SUPPORT) || \ + defined(CONFIG_SPL_SHA384_SUPPORT) +#define IMAGE_ENABLE_SHA384 1 +#else +#define IMAGE_ENABLE_SHA384 0 +#endif + +#if defined(CONFIG_FIT_ENABLE_SHA512_SUPPORT) || \ + defined(CONFIG_SPL_SHA512_SUPPORT) +#define IMAGE_ENABLE_SHA512 1 +#else +#define IMAGE_ENABLE_SHA512 0 +#endif + #endif /* IMAGE_ENABLE_FIT */ #ifdef CONFIG_SYS_BOOT_GET_CMDLINE diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/rsa-checksum.h index 02b814d34e3..54e6a73744e 100644 --- a/include/u-boot/rsa-checksum.h +++ b/include/u-boot/rsa-checksum.h @@ -10,6 +10,7 @@ #include #include #include +#include /** * hash_calculate() - Calculate hash over the data diff --git a/include/u-boot/sha512.h b/include/u-boot/sha512.h new file mode 100644 index 00000000000..516729d7750 --- /dev/null +++ b/include/u-boot/sha512.h @@ -0,0 +1,38 @@ +#ifndef _SHA512_H +#define _SHA512_H + +#define SHA384_SUM_LEN 48 +#define SHA384_DER_LEN 19 +#define SHA512_SUM_LEN 64 +#define SHA512_DER_LEN 19 +#define SHA512_BLOCK_SIZE 128 + +#define CHUNKSZ_SHA384 (16 * 1024) +#define CHUNKSZ_SHA512 (16 * 1024) + +typedef struct { + uint64_t state[SHA512_SUM_LEN / 8]; + uint64_t count[2]; + uint8_t buf[SHA512_BLOCK_SIZE]; +} sha512_context; + +extern const uint8_t sha512_der_prefix[]; + +void sha512_starts(sha512_context * ctx); +void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length); +void sha512_finish(sha512_context * ctx, uint8_t digest[SHA512_SUM_LEN]); + +void sha512_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz); + +extern const uint8_t sha384_der_prefix[]; + +void sha384_starts(sha512_context * ctx); +void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length); +void sha384_finish(sha512_context * ctx, uint8_t digest[SHA384_SUM_LEN]); + +void sha384_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz); + + +#endif /* _SHA512_H */ diff --git a/lib/Kconfig b/lib/Kconfig index af5c38afd98..fc7d68487b2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -345,6 +345,29 @@ config SHA256 The SHA256 algorithm produces a 256-bit (32-byte) hash value (digest). +config SHA512_ALGO + bool "Enable SHA512 algorithm" + help + This option enables support of internal SHA512 algorithm. + +config SHA512 + bool "Enable SHA512 support" + depends on SHA512_ALGO + help + This option enables support of hashing using SHA512 algorithm. + The hash is calculated in software. + The SHA512 algorithm produces a 512-bit (64-byte) hash value + (digest). + +config SHA384 + bool "Enable SHA384 support" + depends on SHA512_ALGO + help + This option enables support of hashing using SHA384 algorithm. + The hash is calculated in software. + The SHA384 algorithm produces a 384-bit (48-byte) hash value + (digest). + config SHA_HW_ACCEL bool "Enable hashing using hardware" help diff --git a/lib/Makefile b/lib/Makefile index dc5761966c4..1dc06c57d5f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_$(SPL_)MD5) += md5.o obj-$(CONFIG_$(SPL_)RSA) += rsa/ obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o +obj-$(CONFIG_SHA512_ALGO) += sha512.o obj-$(CONFIG_$(SPL_)ZLIB) += zlib/ obj-$(CONFIG_$(SPL_)ZSTD) += zstd/ diff --git a/lib/sha512.c b/lib/sha512.c new file mode 100644 index 00000000000..f1e2acf0fbc --- /dev/null +++ b/lib/sha512.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * FIPS-180-2 compliant SHA-512 and SHA-384 implementation + * + * SHA-512 code by Jean-Luc Cooke + * + * Copyright (c) Jean-Luc Cooke + * Copyright (c) Andrew McDonald + * Copyright (c) 2003 Kyle McMartin + * Copyright (c) 2020 Reuben Dowle + */ + +#ifndef USE_HOSTCC +#include +#include +#else +#include +#endif /* USE_HOSTCC */ +#include +#include + +const uint8_t sha384_der_prefix[SHA384_DER_LEN] = { + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30 +}; + +const uint8_t sha512_der_prefix[SHA512_DER_LEN] = { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 +}; + +#define SHA384_H0 0xcbbb9d5dc1059ed8ULL +#define SHA384_H1 0x629a292a367cd507ULL +#define SHA384_H2 0x9159015a3070dd17ULL +#define SHA384_H3 0x152fecd8f70e5939ULL +#define SHA384_H4 0x67332667ffc00b31ULL +#define SHA384_H5 0x8eb44a8768581511ULL +#define SHA384_H6 0xdb0c2e0d64f98fa7ULL +#define SHA384_H7 0x47b5481dbefa4fa4ULL + +#define SHA512_H0 0x6a09e667f3bcc908ULL +#define SHA512_H1 0xbb67ae8584caa73bULL +#define SHA512_H2 0x3c6ef372fe94f82bULL +#define SHA512_H3 0xa54ff53a5f1d36f1ULL +#define SHA512_H4 0x510e527fade682d1ULL +#define SHA512_H5 0x9b05688c2b3e6c1fULL +#define SHA512_H6 0x1f83d9abfb41bd6bULL +#define SHA512_H7 0x5be0cd19137e2179ULL + +static inline uint64_t Ch(uint64_t x, uint64_t y, uint64_t z) +{ + return z ^ (x & (y ^ z)); +} + +static inline uint64_t Maj(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) | (z & (x | y)); +} + +static const uint64_t sha512_K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +static inline uint64_t ror64(uint64_t word, unsigned int shift) +{ + return (word >> (shift & 63)) | (word << ((-shift) & 63)); +} + +#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39)) +#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41)) +#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) +#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6)) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) { \ + (n) = ( (unsigned long long) (b)[(i) ] << 56 ) \ + | ( (unsigned long long) (b)[(i) + 1] << 48 ) \ + | ( (unsigned long long) (b)[(i) + 2] << 40 ) \ + | ( (unsigned long long) (b)[(i) + 3] << 32 ) \ + | ( (unsigned long long) (b)[(i) + 4] << 24 ) \ + | ( (unsigned long long) (b)[(i) + 5] << 16 ) \ + | ( (unsigned long long) (b)[(i) + 6] << 8 ) \ + | ( (unsigned long long) (b)[(i) + 7] ); \ +} +#endif +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) { \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif + +static inline void LOAD_OP(int I, uint64_t *W, const uint8_t *input) +{ + GET_UINT64_BE(W[I], input, I*8); +} + +static inline void BLEND_OP(int I, uint64_t *W) +{ + W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]); +} + +static void +sha512_transform(uint64_t *state, const uint8_t *input) +{ + uint64_t a, b, c, d, e, f, g, h, t1, t2; + + int i; + uint64_t W[16]; + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + for (i=0; i<80; i+=8) { + if (!(i & 8)) { + int j; + + if (i < 16) { + /* load the input */ + for (j = 0; j < 16; j++) + LOAD_OP(i + j, W, input); + } else { + for (j = 0; j < 16; j++) { + BLEND_OP(i + j, W); + } + } + } + + t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[(i & 15)]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + } + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* erase our data */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; +} + +static void sha512_block_fn(sha512_context *sst, const uint8_t *src, + int blocks) +{ + while (blocks--) { + sha512_transform(sst->state, src); + src += SHA512_BLOCK_SIZE; + } +} + +static void sha512_base_do_update(sha512_context *sctx, + const uint8_t *data, + unsigned int len) +{ + unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; + + sctx->count[0] += len; + if (sctx->count[0] < len) + sctx->count[1]++; + + if (unlikely((partial + len) >= SHA512_BLOCK_SIZE)) { + int blocks; + + if (partial) { + int p = SHA512_BLOCK_SIZE - partial; + + memcpy(sctx->buf + partial, data, p); + data += p; + len -= p; + + sha512_block_fn(sctx, sctx->buf, 1); + } + + blocks = len / SHA512_BLOCK_SIZE; + len %= SHA512_BLOCK_SIZE; + + if (blocks) { + sha512_block_fn(sctx, data, blocks); + data += blocks * SHA512_BLOCK_SIZE; + } + partial = 0; + } + if (len) + memcpy(sctx->buf + partial, data, len); +} + +static void sha512_base_do_finalize(sha512_context *sctx) +{ + const int bit_offset = SHA512_BLOCK_SIZE - sizeof(uint64_t[2]); + uint64_t *bits = (uint64_t *)(sctx->buf + bit_offset); + unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; + + sctx->buf[partial++] = 0x80; + if (partial > bit_offset) { + memset(sctx->buf + partial, 0x0, SHA512_BLOCK_SIZE - partial); + partial = 0; + + sha512_block_fn(sctx, sctx->buf, 1); + } + + memset(sctx->buf + partial, 0x0, bit_offset - partial); + bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61); + bits[1] = cpu_to_be64(sctx->count[0] << 3); + sha512_block_fn(sctx, sctx->buf, 1); +} + +#if defined(CONFIG_SHA384) +void sha384_starts(sha512_context * ctx) +{ + ctx->state[0] = SHA384_H0; + ctx->state[1] = SHA384_H1; + ctx->state[2] = SHA384_H2; + ctx->state[3] = SHA384_H3; + ctx->state[4] = SHA384_H4; + ctx->state[5] = SHA384_H5; + ctx->state[6] = SHA384_H6; + ctx->state[7] = SHA384_H7; + ctx->count[0] = ctx->count[1] = 0; +} + +void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length) +{ + sha512_base_do_update(ctx, input, length); +} + +void sha384_finish(sha512_context * ctx, uint8_t digest[SHA384_SUM_LEN]) +{ + int i; + + sha512_base_do_finalize(ctx); + for(i=0; istate[i], digest, i * 8); +} + +/* + * Output = SHA-512( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha384_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha512_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha384_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha384_update(&ctx, curr, chunk); + curr += chunk; + WATCHDOG_RESET(); + } +#else + sha384_update(&ctx, input, ilen); +#endif + + sha384_finish(&ctx, output); +} + +#endif + +#if defined(CONFIG_SHA512) +void sha512_starts(sha512_context * ctx) +{ + ctx->state[0] = SHA512_H0; + ctx->state[1] = SHA512_H1; + ctx->state[2] = SHA512_H2; + ctx->state[3] = SHA512_H3; + ctx->state[4] = SHA512_H4; + ctx->state[5] = SHA512_H5; + ctx->state[6] = SHA512_H6; + ctx->state[7] = SHA512_H7; + ctx->count[0] = ctx->count[1] = 0; +} + +void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length) +{ + sha512_base_do_update(ctx, input, length); +} + +void sha512_finish(sha512_context * ctx, uint8_t digest[SHA512_SUM_LEN]) +{ + int i; + + sha512_base_do_finalize(ctx); + for(i=0; istate[i], digest, i * 8); +} + +/* + * Output = SHA-512( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha512_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha512_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha512_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha512_update(&ctx, curr, chunk); + curr += chunk; + WATCHDOG_RESET(); + } +#else + sha512_update(&ctx, input, ilen); +#endif + + sha512_finish(&ctx, output); +} +#endif diff --git a/tools/Makefile b/tools/Makefile index 879c3fd4a74..51123fd9298 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -107,6 +107,7 @@ dumpimage-mkimage-objs := aisimage.o \ lib/crc16.o \ lib/sha1.o \ lib/sha256.o \ + lib/sha512.o \ common/hash.o \ ublimage.o \ zynqimage.o \ @@ -225,6 +226,7 @@ HOSTCFLAGS_crc8.o := -pedantic HOSTCFLAGS_md5.o := -pedantic HOSTCFLAGS_sha1.o := -pedantic HOSTCFLAGS_sha256.o := -pedantic +HOSTCFLAGS_sha512.o := -pedantic -DCONFIG_SHA512 -DCONFIG_SHA384 quiet_cmd_wrap = WRAP $@ cmd_wrap = echo "\#include <../$(patsubst $(obj)/%,%,$@)>" >$@ -- cgit v1.3.1 From 60ffcf218fb2ed73dac1bd44ef0d45661b7577db Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 24 Jun 2020 06:41:15 -0400 Subject: lib: Always set errno in hcreate_r This could give a confusing error message if it failed and didn't set errno. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- lib/hashtable.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/hashtable.c b/lib/hashtable.c index b96dbe19be4..7b6781bc354 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -110,8 +110,10 @@ int hcreate_r(size_t nel, struct hsearch_data *htab) } /* There is still another table active. Return with error. */ - if (htab->table != NULL) + if (htab->table != NULL) { + __set_errno(EINVAL); return 0; + } /* Change nel to the first prime number not smaller as nel. */ nel |= 1; /* make odd */ @@ -124,8 +126,10 @@ int hcreate_r(size_t nel, struct hsearch_data *htab) /* allocate memory and zero out */ htab->table = (struct env_entry_node *)calloc(htab->size + 1, sizeof(struct env_entry_node)); - if (htab->table == NULL) + if (htab->table == NULL) { + __set_errno(ENOMEM); return 0; + } /* everything went alright */ return 1; -- cgit v1.3.1 From 67f51b40cacc70da44779cef0edb845fa0f0505d Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 14 May 2020 08:30:06 -0400 Subject: compiler*.h: sync include/linux/compiler*.h with Linux 5.7-rc5 Copy these from Linux v5.7-rc5 tag. This brings in some handy new attributes and is otherwise important to keep in sync. We drop the reference to smp_read_barrier_depends() as it is not relevant on the architectures we support at this time, based on where it's implemented in Linux today. We drop the call to kasan_check_read() as that is not relevant to U-Boot as well. Cc: Masahiro Yamada Signed-off-by: Tom Rini --- Kconfig | 3 + include/linux/compiler-clang.h | 44 +++- include/linux/compiler-gcc.h | 259 ++++++------------- include/linux/compiler-intel.h | 17 +- include/linux/compiler.h | 502 +++++++++++------------------------- include/linux/compiler_attributes.h | 273 ++++++++++++++++++++ include/linux/compiler_types.h | 237 +++++++++++++++++ lib/vsprintf.c | 2 - 8 files changed, 777 insertions(+), 560 deletions(-) create mode 100644 include/linux/compiler_attributes.h create mode 100644 include/linux/compiler_types.h (limited to 'lib') diff --git a/Kconfig b/Kconfig index 97707e65a2f..83a3a7e1428 100644 --- a/Kconfig +++ b/Kconfig @@ -71,6 +71,9 @@ config CC_COVERAGE Enabling this option will pass "--coverage" to gcc to compile and link code instrumented for coverage analysis. +config CC_HAS_ASM_INLINE + def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null) + config DISTRO_DEFAULTS bool "Select defaults suitable for booting general purpose Linux distributions" select AUTO_COMPLETE diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h index d1e49d52b64..333a6695a91 100644 --- a/include/linux/compiler-clang.h +++ b/include/linux/compiler-clang.h @@ -1,12 +1,44 @@ -#ifndef __LINUX_COMPILER_H +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_COMPILER_TYPES_H #error "Please don't include directly, include instead." #endif -/* Some compiler specific definitions are overwritten here - * for Clang compiler - */ +/* Compiler specific definitions for Clang compiler */ -#ifdef uninitialized_var -#undef uninitialized_var #define uninitialized_var(x) x = *(&(x)) + +/* same as gcc, this was present in clang-2.6 so we can assume it works + * with any version that can compile the kernel + */ +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +/* all clang versions usable with the kernel support KASAN ABI version 5 */ +#define KASAN_ABI_VERSION 5 + +#if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer) +/* emulate gcc's __SANITIZE_ADDRESS__ flag */ +#define __SANITIZE_ADDRESS__ +#define __no_sanitize_address \ + __attribute__((no_sanitize("address", "hwaddress"))) +#else +#define __no_sanitize_address #endif + +/* + * Not all versions of clang implement the the type-generic versions + * of the builtin overflow checkers. Fortunately, clang implements + * __has_builtin allowing us to avoid awkward version + * checks. Unfortunately, we don't know which version of gcc clang + * pretends to be, so the macro may or may not be defined. + */ +#if __has_builtin(__builtin_mul_overflow) && \ + __has_builtin(__builtin_add_overflow) && \ + __has_builtin(__builtin_sub_overflow) +#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 +#endif + +/* The following are for compatibility with GCC, from compiler-gcc.h, + * and may be redefined here because they should not be shared with other + * compilers, like ICC. + */ +#define barrier() __asm__ __volatile__("" : : : "memory") diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 8d9e0794351..d7ee4c6bad4 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -1,4 +1,5 @@ -#ifndef __LINUX_COMPILER_H +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_COMPILER_TYPES_H #error "Please don't include directly, include instead." #endif @@ -9,11 +10,14 @@ + __GNUC_MINOR__ * 100 \ + __GNUC_PATCHLEVEL__) +#if GCC_VERSION < 40600 +# error Sorry, your compiler is too old - please upgrade it. +#endif + /* Optimization barrier */ /* The "volatile" is due to gcc bugs */ -#define barrier() \ - __asm__ __volatile__("": : :"memory") +#define barrier() __asm__ __volatile__("": : :"memory") /* * This version is i.e. to prevent dead stores elimination on @ptr * where gcc and llvm may behave differently when otherwise using @@ -22,13 +26,12 @@ * clobbered. The issue is as follows: while the inline asm might * access any memory it wants, the compiler could have fit all of * @ptr into memory registers instead, and since @ptr never escaped - * from that, it proofed that the inline asm wasn't touching any of + * from that, it proved that the inline asm wasn't touching any of * it. This version works well with both compilers, i.e. we're telling * the compiler that the inline asm absolutely may see the contents * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495 */ -#define barrier_data(ptr) \ - __asm__ __volatile__("": :"r"(ptr) :"memory") +#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory") /* * This macro obfuscates arithmetic on a variable address so that gcc @@ -55,181 +58,54 @@ (typeof(ptr)) (__ptr + (off)); \ }) -/* Make the optimizer believe the variable can be manipulated arbitrarily. */ -#define OPTIMIZER_HIDE_VAR(var) \ - __asm__ ("" : "=r" (var) : "0" (var)) - -#ifdef __CHECKER__ -#define __must_be_array(a) 0 -#else -/* &a[0] degrades to a pointer: a different type from an array */ -#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) -#endif - -/* - * Force always-inline if the user requests it so via the .config, - * or if gcc is too old: - */ -#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \ - !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4) -#define inline inline __attribute__((always_inline)) notrace -#define __inline__ __inline__ __attribute__((always_inline)) notrace -#define __inline __inline __attribute__((always_inline)) notrace -#else -/* A lot of inline functions can cause havoc with function tracing */ -#define inline inline notrace -#define __inline__ __inline__ notrace -#define __inline __inline notrace -#endif - -#define __always_inline inline __attribute__((always_inline)) -#define noinline __attribute__((noinline)) - -#define __deprecated __attribute__((deprecated)) -#define __packed __attribute__((packed)) -#define __weak __attribute__((weak)) -#define __alias(symbol) __attribute__((alias(#symbol))) - /* - * it doesn't make sense on ARM (currently the only user of __naked) - * to trace naked functions because then mcount is called without - * stack and frame pointer being set up and there is no chance to - * restore the lr register to the value before mcount was called. - * - * The asm() bodies of naked functions often depend on standard calling - * conventions, therefore they must be noinline and noclone. - * - * GCC 4.[56] currently fail to enforce this, so we must do so ourselves. - * See GCC PR44290. - */ -#define __naked __attribute__((naked)) noinline __noclone notrace - -#define __noreturn __attribute__((noreturn)) - -/* - * From the GCC manual: - * - * Many functions have no effects except the return value and their - * return value depends only on the parameters and/or global - * variables. Such a function can be subject to common subexpression - * elimination and loop optimization just as an arithmetic operator - * would be. - * [...] + * A trick to suppress uninitialized variable warning without generating any + * code */ -#define __pure __attribute__((pure)) -#define __aligned(x) __attribute__((aligned(x))) -#define __printf(a, b) __attribute__((format(printf, a, b))) -#define __scanf(a, b) __attribute__((format(scanf, a, b))) -#define __attribute_const__ __attribute__((__const__)) -#define __maybe_unused __attribute__((unused)) -#define __always_unused __attribute__((unused)) - -/* gcc version specific checks */ - -#if GCC_VERSION < 30200 -# error Sorry, your compiler is too old - please upgrade it. -#endif - -#if GCC_VERSION < 30300 -# define __used __attribute__((__unused__)) -#else -# define __used __attribute__((__used__)) -#endif - -#ifdef CONFIG_GCOV_KERNEL -# if GCC_VERSION < 30400 -# error "GCOV profiling support for gcc versions below 3.4 not included" -# endif /* __GNUC_MINOR__ */ -#endif /* CONFIG_GCOV_KERNEL */ +#define uninitialized_var(x) x = x -#if GCC_VERSION >= 30400 -#define __must_check __attribute__((warn_unused_result)) +#ifdef CONFIG_RETPOLINE +#define __noretpoline __attribute__((__indirect_branch__("keep"))) #endif -#if GCC_VERSION >= 40000 +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) -/* GCC 4.1.[01] miscompiles __weak */ -#ifdef __KERNEL__ -# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101 -# error Your version of gcc miscompiles the __weak directive -# endif -#endif +#define __compiletime_object_size(obj) __builtin_object_size(obj, 0) -#define __used __attribute__((__used__)) -#define __compiler_offsetof(a, b) \ - __builtin_offsetof(a, b) +#define __compiletime_warning(message) __attribute__((__warning__(message))) +#define __compiletime_error(message) __attribute__((__error__(message))) -#if GCC_VERSION >= 40100 && GCC_VERSION < 40600 -# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) +#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__) +#define __latent_entropy __attribute__((latent_entropy)) #endif -#if GCC_VERSION >= 40300 -/* Mark functions as cold. gcc will assume any path leading to a call - * to them will be unlikely. This means a lot of manual unlikely()s - * are unnecessary now for any paths leading to the usual suspects - * like BUG(), printk(), panic() etc. [but let's keep them for now for - * older compilers] - * - * Early snapshots of gcc 4.3 don't support this and we can't detect this - * in the preprocessor, but we can live with this because they're unreleased. - * Maketime probing would be overkill here. +/* + * calling noreturn functions, __builtin_unreachable() and __builtin_trap() + * confuse the stack allocation in gcc, leading to overly large stack + * frames, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 * - * gcc also has a __attribute__((__hot__)) to move hot functions into - * a special section, but I don't see any sense in this right now in - * the kernel context + * Adding an empty inline assembly before it works around the problem */ -#define __cold __attribute__((__cold__)) - -#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) +#define barrier_before_unreachable() asm volatile("") -#ifndef __CHECKER__ -# define __compiletime_warning(message) __attribute__((warning(message))) -# define __compiletime_error(message) __attribute__((error(message))) -#endif /* __CHECKER__ */ -#endif /* GCC_VERSION >= 40300 */ - -#if GCC_VERSION >= 40500 /* * Mark a position in code as unreachable. This can be used to * suppress control flow warnings after asm blocks that transfer * control elsewhere. - * - * Early snapshots of gcc 4.5 don't support this and we can't detect - * this in the preprocessor, but we can live with this because they're - * unreleased. Really, we need to have autoconf for the kernel. - */ -#define unreachable() __builtin_unreachable() - -/* Mark a function definition as prohibited from being cloned. */ -#define __noclone __attribute__((__noclone__)) - -#endif /* GCC_VERSION >= 40500 */ - -#if GCC_VERSION >= 40600 -/* - * When used with Link Time Optimization, gcc can optimize away C functions or - * variables which are referenced only from assembly code. __visible tells the - * optimizer that something else uses this function or variable, thus preventing - * this. */ -#define __visible __attribute__((externally_visible)) -#endif - +#define unreachable() \ + do { \ + annotate_unreachable(); \ + barrier_before_unreachable(); \ + __builtin_unreachable(); \ + } while (0) -#if GCC_VERSION >= 40900 && !defined(__CHECKER__) -/* - * __assume_aligned(n, k): Tell the optimizer that the returned - * pointer can be assumed to be k modulo n. The second argument is - * optional (default 0), so we use a variadic macro to make the - * shorthand. - * - * Beware: Do not apply this to functions which may return - * ERR_PTRs. Also, it is probably unwise to apply it to functions - * returning extra information in the low bits (but in that case the - * compiler should see some alignment anyway, when the return value is - * massaged by 'flags = ptr & 3; ptr &= ~3;'). - */ -#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__))) +#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__) +#define __randomize_layout __attribute__((randomize_layout)) +#define __no_randomize_layout __attribute__((no_randomize_layout)) +/* This anon struct can add padding, so only enable it under randstruct. */ +#define randomized_struct_fields_start struct { +#define randomized_struct_fields_end } __randomize_layout; #endif /* @@ -243,43 +119,56 @@ */ #define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) -#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP -#if GCC_VERSION >= 40400 +/* + * sparse (__CHECKER__) pretends to be gcc, but can't do constant + * folding in __builtin_bswap*() (yet), so don't set these for it. + */ +#if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP) && !defined(__CHECKER__) #define __HAVE_BUILTIN_BSWAP32__ #define __HAVE_BUILTIN_BSWAP64__ -#endif -#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600) +#if GCC_VERSION >= 40800 #define __HAVE_BUILTIN_BSWAP16__ #endif -#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ +#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP && !__CHECKER__ */ -#if GCC_VERSION >= 50000 +#if GCC_VERSION >= 70000 +#define KASAN_ABI_VERSION 5 +#elif GCC_VERSION >= 50000 #define KASAN_ABI_VERSION 4 #elif GCC_VERSION >= 40902 #define KASAN_ABI_VERSION 3 #endif -#if GCC_VERSION >= 40902 -/* - * Tell the compiler that address safety instrumentation (KASAN) - * should not be applied to that function. - * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368 - */ +#if __has_attribute(__no_sanitize_address__) #define __no_sanitize_address __attribute__((no_sanitize_address)) +#else +#define __no_sanitize_address #endif -#endif /* gcc version >= 40000 specific checks */ - -#if !defined(__noclone) -#define __noclone /* not needed */ -#endif - -#if !defined(__no_sanitize_address) -#define __no_sanitize_address +#if GCC_VERSION >= 50100 +#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 #endif /* - * A trick to suppress uninitialized variable warning without generating any - * code + * Turn individual warnings and errors on and off locally, depending + * on version. */ -#define uninitialized_var(x) x = x +#define __diag_GCC(version, severity, s) \ + __diag_GCC_ ## version(__diag_GCC_ ## severity s) + +/* Severity used in pragma directives */ +#define __diag_GCC_ignore ignored +#define __diag_GCC_warn warning +#define __diag_GCC_error error + +#define __diag_str1(s) #s +#define __diag_str(s) __diag_str1(s) +#define __diag(s) _Pragma(__diag_str(GCC diagnostic s)) + +#if GCC_VERSION >= 80000 +#define __diag_GCC_8(s) __diag(s) +#else +#define __diag_GCC_8(s) +#endif + +#define __no_fgcse __attribute__((optimize("-fno-gcse"))) diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h index d4c71132d07..b17f3cd1833 100644 --- a/include/linux/compiler-intel.h +++ b/include/linux/compiler-intel.h @@ -1,22 +1,17 @@ -#ifndef __LINUX_COMPILER_H +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_COMPILER_TYPES_H #error "Please don't include directly, include instead." #endif #ifdef __ECC -/* Some compiler specific definitions are overwritten here - * for Intel ECC compiler - */ +/* Compiler specific definitions for Intel ECC compiler */ #include /* Intel ECC compiler doesn't support gcc specific asm stmts. * It uses intrinsics to do the equivalent things. */ -#undef barrier -#undef barrier_data -#undef RELOC_HIDE -#undef OPTIMIZER_HIDE_VAR #define barrier() __memory_barrier() #define barrier_data(ptr) barrier() @@ -32,14 +27,8 @@ */ #define OPTIMIZER_HIDE_VAR(var) barrier() -/* Intel ECC compiler doesn't support __builtin_types_compatible_p() */ -#define __must_be_array(a) 0 - #endif -#ifndef __HAVE_BUILTIN_BSWAP16__ /* icc has this, but it's called _bswap16 */ #define __HAVE_BUILTIN_BSWAP16__ #define __builtin_bswap16 _bswap16 -#endif - diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 0ea6c8fccaa..5e3b3c08e91 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -1,127 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LINUX_COMPILER_H #define __LINUX_COMPILER_H -#ifndef __ASSEMBLY__ +#include -#ifdef __CHECKER__ -# define __user __attribute__((noderef, address_space(1))) -# define __kernel __attribute__((address_space(0))) -# define __safe __attribute__((safe)) -# define __force __attribute__((force)) -# define __nocast __attribute__((nocast)) -# define __iomem __attribute__((noderef, address_space(2))) -# define __must_hold(x) __attribute__((context(x,1,1))) -# define __acquires(x) __attribute__((context(x,0,1))) -# define __releases(x) __attribute__((context(x,1,0))) -# define __acquire(x) __context__(x,1) -# define __release(x) __context__(x,-1) -# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) -# define __percpu __attribute__((noderef, address_space(3))) -# define __pmem __attribute__((noderef, address_space(5))) -#ifdef CONFIG_SPARSE_RCU_POINTER -# define __rcu __attribute__((noderef, address_space(4))) -#else -# define __rcu -#endif -extern void __chk_user_ptr(const volatile void __user *); -extern void __chk_io_ptr(const volatile void __iomem *); -#else -# define __user -# define __kernel -# define __safe -# define __force -# define __nocast -# define __iomem -# define __chk_user_ptr(x) (void)0 -# define __chk_io_ptr(x) (void)0 -# define __builtin_warning(x, y...) (1) -# define __must_hold(x) -# define __acquires(x) -# define __releases(x) -# define __acquire(x) (void)0 -# define __release(x) (void)0 -# define __cond_lock(x,c) (c) -# define __percpu -# define __rcu -# define __pmem -#endif - -/* Indirect macros required for expanded argument pasting, eg. __LINE__. */ -#define ___PASTE(a,b) a##b -#define __PASTE(a,b) ___PASTE(a,b) +#ifndef __ASSEMBLY__ #ifdef __KERNEL__ -#ifdef __GNUC__ -#include -#endif - -#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__) -#define notrace __attribute__((hotpatch(0,0))) -#else -#define notrace __attribute__((no_instrument_function)) -#endif - -/* Intel compiler defines __GNUC__. So we will overwrite implementations - * coming from above header files here - */ -#ifdef __INTEL_COMPILER -# include -#endif - -/* Clang compiler defines __GNUC__. So we will overwrite implementations - * coming from above header files here - */ -#ifdef __clang__ -#include -#endif - -/* - * Generic compiler-dependent macros required for kernel - * build go below this comment. Actual compiler/compiler version - * specific implementations come from the above header files - */ - -struct ftrace_branch_data { - const char *func; - const char *file; - unsigned line; - union { - struct { - unsigned long correct; - unsigned long incorrect; - }; - struct { - unsigned long miss; - unsigned long hit; - }; - unsigned long miss_hit[2]; - }; -}; - /* * Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code * to disable branch tracing on a per file basis. */ #if defined(CONFIG_TRACE_BRANCH_PROFILING) \ && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__) -void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); +void ftrace_likely_update(struct ftrace_likely_data *f, int val, + int expect, int is_constant); #define likely_notrace(x) __builtin_expect(!!(x), 1) #define unlikely_notrace(x) __builtin_expect(!!(x), 0) -#define __branch_check__(x, expect) ({ \ - int ______r; \ - static struct ftrace_branch_data \ - __attribute__((__aligned__(4))) \ - __attribute__((section("_ftrace_annotated_branch"))) \ +#define __branch_check__(x, expect, is_constant) ({ \ + long ______r; \ + static struct ftrace_likely_data \ + __aligned(4) \ + __section(_ftrace_annotated_branch) \ ______f = { \ - .func = __func__, \ - .file = __FILE__, \ - .line = __LINE__, \ + .data.func = __func__, \ + .data.file = __FILE__, \ + .data.line = __LINE__, \ }; \ - ______r = likely_notrace(x); \ - ftrace_likely_update(&______f, ______r, expect); \ + ______r = __builtin_expect(!!(x), expect); \ + ftrace_likely_update(&______f, ______r, \ + expect, is_constant); \ ______r; \ }) @@ -131,10 +42,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); * written by Daniel Walker. */ # ifndef likely -# define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1)) +# define likely(x) (__branch_check__(x, 1, __builtin_constant_p(x))) # endif # ifndef unlikely -# define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) +# define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x))) # endif #ifdef CONFIG_PROFILE_ALL_BRANCHES @@ -142,23 +53,24 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); * "Define 'is'", Bill Clinton * "Define 'if'", Steven Rostedt */ -#define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) -#define __trace_if(cond) \ - if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ - ({ \ - int ______r; \ - static struct ftrace_branch_data \ - __attribute__((__aligned__(4))) \ - __attribute__((section("_ftrace_branch"))) \ - ______f = { \ - .func = __func__, \ - .file = __FILE__, \ - .line = __LINE__, \ - }; \ - ______r = !!(cond); \ - ______f.miss_hit[______r]++; \ - ______r; \ - })) +#define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) ) + +#define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond)) + +#define __trace_if_value(cond) ({ \ + static struct ftrace_branch_data \ + __aligned(4) \ + __section(_ftrace_branch) \ + __if_trace = { \ + .func = __func__, \ + .file = __FILE__, \ + .line = __LINE__, \ + }; \ + (cond) ? \ + (__if_trace.miss_hit[1]++,1) : \ + (__if_trace.miss_hit[0]++,0); \ +}) + #endif /* CONFIG_PROFILE_ALL_BRANCHES */ #else @@ -175,9 +87,76 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); # define barrier_data(ptr) barrier() #endif +/* workaround for GCC PR82365 if needed */ +#ifndef barrier_before_unreachable +# define barrier_before_unreachable() do { } while (0) +#endif + /* Unreachable code */ +#ifdef CONFIG_STACK_VALIDATION +/* + * These macros help objtool understand GCC code flow for unreachable code. + * The __COUNTER__ based labels are a hack to make each instance of the macros + * unique, to convince GCC not to merge duplicate inline asm statements. + */ +#define annotate_reachable() ({ \ + asm volatile("%c0:\n\t" \ + ".pushsection .discard.reachable\n\t" \ + ".long %c0b - .\n\t" \ + ".popsection\n\t" : : "i" (__COUNTER__)); \ +}) +#define annotate_unreachable() ({ \ + asm volatile("%c0:\n\t" \ + ".pushsection .discard.unreachable\n\t" \ + ".long %c0b - .\n\t" \ + ".popsection\n\t" : : "i" (__COUNTER__)); \ +}) +#define ASM_UNREACHABLE \ + "999:\n\t" \ + ".pushsection .discard.unreachable\n\t" \ + ".long 999b - .\n\t" \ + ".popsection\n\t" + +/* Annotate a C jump table to allow objtool to follow the code flow */ +#define __annotate_jump_table __section(.rodata..c_jump_table) + +#else +#define annotate_reachable() +#define annotate_unreachable() +#define __annotate_jump_table +#endif + +#ifndef ASM_UNREACHABLE +# define ASM_UNREACHABLE +#endif #ifndef unreachable -# define unreachable() do { } while (1) +# define unreachable() do { \ + annotate_unreachable(); \ + __builtin_unreachable(); \ +} while (0) +#endif + +/* + * KENTRY - kernel entry point + * This can be used to annotate symbols (functions or data) that are used + * without their linker symbol being referenced explicitly. For example, + * interrupt vector handlers, or functions in the kernel image that are found + * programatically. + * + * Not required for symbols exported with EXPORT_SYMBOL, or initcalls. Those + * are handled in their own way (with KEEP() in linker scripts). + * + * KENTRY can be avoided if the symbols in question are marked as KEEP() in the + * linker script. For example an architecture could KEEP() its entire + * boot/exception vector code rather than annotate each function and data. + */ +#ifndef KENTRY +# define KENTRY(sym) \ + extern typeof(sym) sym; \ + static const unsigned long __kentry_##sym \ + __used \ + __section("___kentry" "+" #sym ) \ + = (unsigned long)&sym; #endif #ifndef RELOC_HIDE @@ -188,7 +167,9 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); #endif #ifndef OPTIMIZER_HIDE_VAR -#define OPTIMIZER_HIDE_VAR(var) barrier() +/* Make the optimizer believe the variable can be manipulated arbitrarily. */ +#define OPTIMIZER_HIDE_VAR(var) \ + __asm__ ("" : "=r" (var) : "0" (var)) #endif /* Not-quite-unique ID. */ @@ -220,23 +201,21 @@ void __read_once_size(const volatile void *p, void *res, int size) #ifdef CONFIG_KASAN /* - * This function is not 'inline' because __no_sanitize_address confilcts + * We can't declare function 'inline' because __no_sanitize_address confilcts * with inlining. Attempt to inline it may cause a build failure. * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368 * '__maybe_unused' allows us to avoid defined-but-not-used warnings. */ -static __no_sanitize_address __maybe_unused -void __read_once_size_nocheck(const volatile void *p, void *res, int size) -{ - __READ_ONCE_SIZE; -} +# define __no_kasan_or_inline __no_sanitize_address notrace __maybe_unused #else -static __always_inline +# define __no_kasan_or_inline __always_inline +#endif + +static __no_kasan_or_inline void __read_once_size_nocheck(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; } -#endif static __always_inline void __write_once_size(volatile void *p, void *res, int size) { @@ -255,20 +234,21 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s /* * Prevent the compiler from merging or refetching reads or writes. The * compiler is also forbidden from reordering successive instances of - * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the - * compiler is aware of some particular ordering. One way to make the - * compiler aware of ordering is to put the two invocations of READ_ONCE, - * WRITE_ONCE or ACCESS_ONCE() in different C statements. + * READ_ONCE and WRITE_ONCE, but only when the compiler is aware of some + * particular ordering. One way to make the compiler aware of ordering is to + * put the two invocations of READ_ONCE or WRITE_ONCE in different C + * statements. * - * In contrast to ACCESS_ONCE these two macros will also work on aggregate - * data types like structs or unions. If the size of the accessed data - * type exceeds the word size of the machine (e.g., 32 bits or 64 bits) - * READ_ONCE() and WRITE_ONCE() will fall back to memcpy and print a - * compile-time warning. + * These two macros will also work on aggregate data types like structs or + * unions. If the size of the accessed data type exceeds the word size of + * the machine (e.g., 32 bits or 64 bits) READ_ONCE() and WRITE_ONCE() will + * fall back to memcpy(). There's at least two memcpy()s: one for the + * __builtin_memcpy() and then one for the macro doing the copy of variable + * - '__u' allocated on the stack. * * Their two major use cases are: (1) Mediating communication between * process-level code and irq/NMI handlers, all running on the same CPU, - * and (2) Ensuring that the compiler does not fold, spindle, or otherwise + * and (2) Ensuring that the compiler does not fold, spindle, or otherwise * mutilate accesses that either do not require ordering or that interact * with an explicit memory barrier or atomic instruction that provides the * required ordering. @@ -291,6 +271,12 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s */ #define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0) +static __no_kasan_or_inline +unsigned long read_word_at_a_time(const void *addr) +{ + return *(unsigned long *)addr; +} + #define WRITE_ONCE(x, val) \ ({ \ union { typeof(x) __val; char __c[1]; } __u = \ @@ -299,158 +285,28 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s __u.__val; \ }) -/** - * smp_cond_acquire() - Spin wait for cond with ACQUIRE ordering - * @cond: boolean expression to wait for - * - * Equivalent to using smp_load_acquire() on the condition variable but employs - * the control dependency of the wait to reduce the barrier on many platforms. - * - * The control dependency provides a LOAD->STORE order, the additional RMB - * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order, - * aka. ACQUIRE. - */ -#define smp_cond_acquire(cond) do { \ - while (!(cond)) \ - cpu_relax(); \ - smp_rmb(); /* ctrl + rmb := acquire */ \ -} while (0) - -#endif /* __KERNEL__ */ - -#endif /* __ASSEMBLY__ */ - -#ifdef __KERNEL__ -/* - * Allow us to mark functions as 'deprecated' and have gcc emit a nice - * warning for each use, in hopes of speeding the functions removal. - * Usage is: - * int __deprecated foo(void) - */ -#ifndef __deprecated -# define __deprecated /* unimplemented */ -#endif - -#ifdef MODULE -#define __deprecated_for_modules __deprecated -#else -#define __deprecated_for_modules -#endif - -#ifndef __must_check -#define __must_check -#endif - -#ifndef CONFIG_ENABLE_MUST_CHECK -#undef __must_check -#define __must_check -#endif -#ifndef CONFIG_ENABLE_WARN_DEPRECATED -#undef __deprecated -#undef __deprecated_for_modules -#define __deprecated -#define __deprecated_for_modules -#endif - -/* - * Allow us to avoid 'defined but not used' warnings on functions and data, - * as well as force them to be emitted to the assembly file. - * - * As of gcc 3.4, static functions that are not marked with attribute((used)) - * may be elided from the assembly file. As of gcc 3.4, static data not so - * marked will not be elided, but this may change in a future gcc version. - * - * NOTE: Because distributions shipped with a backported unit-at-a-time - * compiler in gcc 3.3, we must define __used to be __attribute__((used)) - * for gcc >=3.3 instead of 3.4. - * - * In prior versions of gcc, such functions and data would be emitted, but - * would be warned about except with attribute((unused)). - * - * Mark functions that are referenced only in inline assembly as __used so - * the code is emitted even though it appears to be unreferenced. - */ -#ifndef __used -# define __used /* unimplemented */ -#endif - -#ifndef __maybe_unused -# define __maybe_unused /* unimplemented */ -#endif - -#ifndef __always_unused -# define __always_unused /* unimplemented */ -#endif - -#ifndef noinline -#define noinline -#endif - -/* - * Rather then using noinline to prevent stack consumption, use - * noinline_for_stack instead. For documentation reasons. - */ -#define noinline_for_stack noinline - -#ifndef __always_inline -#define __always_inline inline -#endif - #endif /* __KERNEL__ */ /* - * From the GCC manual: - * - * Many functions do not examine any values except their arguments, - * and have no effects except the return value. Basically this is - * just slightly more strict class than the `pure' attribute above, - * since function is not allowed to read global memory. - * - * Note that a function that has pointer arguments and examines the - * data pointed to must _not_ be declared `const'. Likewise, a - * function that calls a non-`const' function usually must not be - * `const'. It does not make sense for a `const' function to return - * `void'. - */ -#ifndef __attribute_const__ -# define __attribute_const__ /* unimplemented */ -#endif - -/* - * Tell gcc if a function is cold. The compiler will assume any path - * directly leading to the call is unlikely. + * Force the compiler to emit 'sym' as a symbol, so that we can reference + * it from inline assembler. Necessary in case 'sym' could be inlined + * otherwise, or eliminated entirely due to lack of references that are + * visible to the compiler. */ +#define __ADDRESSABLE(sym) \ + static void * __section(.discard.addressable) __used \ + __PASTE(__addressable_##sym, __LINE__) = (void *)&sym; -#ifndef __cold -#define __cold -#endif - -/* Simple shorthand for a section definition */ -#ifndef __section -# define __section(S) __attribute__ ((__section__(#S))) -#endif - -#ifndef __visible -#define __visible -#endif - -/* - * Assume alignment of return value. +/** + * offset_to_ptr - convert a relative memory offset to an absolute pointer + * @off: the address of the 32-bit offset value */ -#ifndef __assume_aligned -#define __assume_aligned(a, ...) -#endif - - -/* Are two types/vars the same type (ignoring qualifiers)? */ -#ifndef __same_type -# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) -#endif +static inline void *offset_to_ptr(const int *off) +{ + return (void *)((unsigned long)off + *off); +} -/* Is this type a native word size -- useful for atomic operations */ -#ifndef __native_word -# define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long)) -#endif +#endif /* __ASSEMBLY__ */ /* Compile time object size, -1 for unknown */ #ifndef __compiletime_object_size @@ -461,29 +317,14 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s #endif #ifndef __compiletime_error # define __compiletime_error(message) -/* - * Sparse complains of variable sized arrays due to the temporary variable in - * __compiletime_assert. Unfortunately we can't just expand it out to make - * sparse see a constant array size without breaking compiletime_assert on old - * versions of GCC (e.g. 4.2.4), so hide the array from sparse altogether. - */ -# ifndef __CHECKER__ -# define __compiletime_error_fallback(condition) \ - do { ((void)sizeof(char[1 - 2 * condition])); } while (0) -# endif -#endif -#ifndef __compiletime_error_fallback -# define __compiletime_error_fallback(condition) do { } while (0) #endif #ifdef __OPTIMIZE__ # define __compiletime_assert(condition, msg, prefix, suffix) \ do { \ - bool __cond = !(condition); \ extern void prefix ## suffix(void) __compiletime_error(msg); \ - if (__cond) \ + if (!(condition)) \ prefix ## suffix(); \ - __compiletime_error_fallback(__cond); \ } while (0) #else # define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0) @@ -502,58 +343,13 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s * compiler has support to do so. */ #define compiletime_assert(condition, msg) \ - _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) + _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) #define compiletime_assert_atomic_type(t) \ compiletime_assert(__native_word(t), \ "Need native word sized stores/loads for atomicity.") -/* - * Prevent the compiler from merging or refetching accesses. The compiler - * is also forbidden from reordering successive instances of ACCESS_ONCE(), - * but only when the compiler is aware of some particular ordering. One way - * to make the compiler aware of ordering is to put the two invocations of - * ACCESS_ONCE() in different C statements. - * - * ACCESS_ONCE will only work on scalar types. For union types, ACCESS_ONCE - * on a union member will work as long as the size of the member matches the - * size of the union and the size is smaller than word size. - * - * The major use cases of ACCESS_ONCE used to be (1) Mediating communication - * between process-level code and irq/NMI handlers, all running on the same CPU, - * and (2) Ensuring that the compiler does not fold, spindle, or otherwise - * mutilate accesses that either do not require ordering or that interact - * with an explicit memory barrier or atomic instruction that provides the - * required ordering. - * - * If possible use READ_ONCE()/WRITE_ONCE() instead. - */ -#define __ACCESS_ONCE(x) ({ \ - __maybe_unused typeof(x) __var = (__force typeof(x)) 0; \ - (volatile typeof(x) *)&(x); }) -#define ACCESS_ONCE(x) (*__ACCESS_ONCE(x)) - -/** - * lockless_dereference() - safely load a pointer for later dereference - * @p: The pointer to load - * - * Similar to rcu_dereference(), but for situations where the pointed-to - * object's lifetime is managed by something other than RCU. That - * "something other" might be reference counting or simple immortality. - */ -#define lockless_dereference(p) \ -({ \ - typeof(p) _________p1 = READ_ONCE(p); \ - smp_read_barrier_depends(); /* Dependency order vs. p above. */ \ - (_________p1); \ -}) +/* &a[0] degrades to a pointer: a different type from an array */ +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) -/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */ -#ifdef CONFIG_KPROBES -# define __kprobes __attribute__((__section__(".kprobes.text"))) -# define nokprobe_inline __always_inline -#else -# define __kprobes -# define nokprobe_inline inline -#endif #endif /* __LINUX_COMPILER_H */ diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h new file mode 100644 index 00000000000..cdf01659665 --- /dev/null +++ b/include/linux/compiler_attributes.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_COMPILER_ATTRIBUTES_H +#define __LINUX_COMPILER_ATTRIBUTES_H + +/* + * The attributes in this file are unconditionally defined and they directly + * map to compiler attribute(s), unless one of the compilers does not support + * the attribute. In that case, __has_attribute is used to check for support + * and the reason is stated in its comment ("Optional: ..."). + * + * Any other "attributes" (i.e. those that depend on a configuration option, + * on a compiler, on an architecture, on plugins, on other attributes...) + * should be defined elsewhere (e.g. compiler_types.h or compiler-*.h). + * The intention is to keep this file as simple as possible, as well as + * compiler- and version-agnostic (e.g. avoiding GCC_VERSION checks). + * + * This file is meant to be sorted (by actual attribute name, + * not by #define identifier). Use the __attribute__((__name__)) syntax + * (i.e. with underscores) to avoid future collisions with other macros. + * Provide links to the documentation of each supported compiler, if it exists. + */ + +/* + * __has_attribute is supported on gcc >= 5, clang >= 2.9 and icc >= 17. + * In the meantime, to support 4.6 <= gcc < 5, we implement __has_attribute + * by hand. + * + * sparse does not support __has_attribute (yet) and defines __GNUC_MINOR__ + * depending on the compiler used to build it; however, these attributes have + * no semantic effects for sparse, so it does not matter. Also note that, + * in order to avoid sparse's warnings, even the unsupported ones must be + * defined to 0. + */ +#ifndef __has_attribute +# define __has_attribute(x) __GCC4_has_attribute_##x +# define __GCC4_has_attribute___assume_aligned__ (__GNUC_MINOR__ >= 9) +# define __GCC4_has_attribute___copy__ 0 +# define __GCC4_has_attribute___designated_init__ 0 +# define __GCC4_has_attribute___externally_visible__ 1 +# define __GCC4_has_attribute___noclone__ 1 +# define __GCC4_has_attribute___nonstring__ 0 +# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8) +# define __GCC4_has_attribute___fallthrough__ 0 +#endif + +/* + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alias-function-attribute + */ +#define __alias(symbol) __attribute__((__alias__(#symbol))) + +/* + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-aligned-function-attribute + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-aligned-type-attribute + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-aligned-variable-attribute + */ +#define __aligned(x) __attribute__((__aligned__(x))) +#define __aligned_largest __attribute__((__aligned__)) + +/* + * Note: users of __always_inline currently do not write "inline" themselves, + * which seems to be required by gcc to apply the attribute according + * to its docs (and also "warning: always_inline function might not be + * inlinable [-Wattributes]" is emitted). + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute + * clang: mentioned + */ +#define __always_inline inline __attribute__((__always_inline__)) + +/* + * The second argument is optional (default 0), so we use a variadic macro + * to make the shorthand. + * + * Beware: Do not apply this to functions which may return + * ERR_PTRs. Also, it is probably unwise to apply it to functions + * returning extra information in the low bits (but in that case the + * compiler should see some alignment anyway, when the return value is + * massaged by 'flags = ptr & 3; ptr &= ~3;'). + * + * Optional: only supported since gcc >= 4.9 + * Optional: not supported by icc + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-assume_005faligned-function-attribute + * clang: https://clang.llvm.org/docs/AttributeReference.html#assume-aligned + */ +#if __has_attribute(__assume_aligned__) +# define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__))) +#else +# define __assume_aligned(a, ...) +#endif + +/* + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-cold-function-attribute + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-cold-label-attribute + */ +#define __cold __attribute__((__cold__)) + +/* + * Note the long name. + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute + */ +#define __attribute_const__ __attribute__((__const__)) + +/* + * Optional: only supported since gcc >= 9 + * Optional: not supported by clang + * Optional: not supported by icc + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute + */ +#if __has_attribute(__copy__) +# define __copy(symbol) __attribute__((__copy__(symbol))) +#else +# define __copy(symbol) +#endif + +/* + * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated' + * attribute warnings entirely and for good") for more information. + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-deprecated-type-attribute + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-deprecated-variable-attribute + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html#index-deprecated-enumerator-attribute + * clang: https://clang.llvm.org/docs/AttributeReference.html#deprecated + */ +#define __deprecated + +/* + * Optional: only supported since gcc >= 5.1 + * Optional: not supported by clang + * Optional: not supported by icc + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-designated_005finit-type-attribute + */ +#if __has_attribute(__designated_init__) +# define __designated_init __attribute__((__designated_init__)) +#else +# define __designated_init +#endif + +/* + * Optional: not supported by clang + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute + */ +#if __has_attribute(__externally_visible__) +# define __visible __attribute__((__externally_visible__)) +#else +# define __visible +#endif + +/* + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-format-function-attribute + * clang: https://clang.llvm.org/docs/AttributeReference.html#format + */ +#define __printf(a, b) __attribute__((__format__(printf, a, b))) +#define __scanf(a, b) __attribute__((__format__(scanf, a, b))) + +/* + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-gnu_005finline-function-attribute + * clang: https://clang.llvm.org/docs/AttributeReference.html#gnu-inline + */ +#define __gnu_inline __attribute__((__gnu_inline__)) + +/* + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute + */ +#define __malloc __attribute__((__malloc__)) + +/* + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-mode-type-attribute + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-mode-variable-attribute + */ +#define __mode(x) __attribute__((__mode__(x))) + +/* + * Optional: not supported by clang + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noclone-function-attribute + */ +#if __has_attribute(__noclone__) +# define __noclone __attribute__((__noclone__)) +#else +# define __noclone +#endif + +/* + * Add the pseudo keyword 'fallthrough' so case statement blocks + * must end with any of these keywords: + * break; + * fallthrough; + * goto