[PATCH] ieee1275 radix support added for KVM on power
This patch adds support for Radix, Xive and Radix_gtse in Options vector5 which is required for KVM LPARs. KVM LPARs ONLY support Radix and not the Hash. Not enabling Radix on any PowerVM KVM LPARs will result in boot failure. Signed-off-by: Avnish Chouhan --- grub-core/kern/ieee1275/init.c | 68 +- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index fb7d1a3..94bbf86 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -113,6 +113,17 @@ grub_addr_t grub_ieee1275_original_stack; #define DRC_INFO0x40 #define BYTE22 (DY_MEM_V2 | DRC_INFO) +/* For ibm,arch-vec-5-platform-support */ + +#define XIVE_INDEX 0x17 +#define MMU_INDEX0x18 +#define RADIX_GTSE_INDEX 0x1a +#define RADIX_ENABLED0x40 +#define XIVE_ENABLED 0x40 +#define HASH_ENABLED 0x0 +#define MAX_SUPPORTED0xC0 +#define RADIX_GTSE_ENABLED 0x40 + void grub_exit (void) { @@ -737,6 +748,10 @@ struct option_vector5 grub_uint32_t platform_facilities; grub_uint8_t sub_processors; grub_uint8_t byte22; + grub_uint8_t xive; + grub_uint8_t mmu; + grub_uint8_t hpt_ext; + grub_uint8_t radix_gtse; } GRUB_PACKED; struct pvr_entry @@ -775,6 +790,13 @@ grub_ieee1275_ibm_cas (void) { int rc; grub_ieee1275_ihandle_t root; + grub_uint8_t ibm_arch_platform_support[8]; + grub_ssize_t actual; + grub_uint8_t xive_support = 0; + grub_uint8_t mmu_support = 0; + grub_uint8_t radix_gtse_support = 0; + int i=0; + int prop_len=8; struct cas_args { struct grub_ieee1275_common_hdr common; @@ -783,6 +805,50 @@ grub_ieee1275_ibm_cas (void) grub_ieee1275_cell_t cas_addr; grub_ieee1275_cell_t result; } args; + + grub_ieee1275_get_integer_property (grub_ieee1275_chosen, + "ibm,arch-vec-5-platform-support", + ibm_arch_platform_support, + sizeof (ibm_arch_platform_support), + &actual); + + for (i=0; ihttps://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v3 2/3] efi: Generate stack protector canary at build time if urandom is available
Generating the canary at build time allows the canary to be different for every build which could limit the effectiveness of certain exploits. Fallback to the statically generated random bytes if /dev/urandom is not readable (eg. Windows). On 32-bit architectures, which use a 32-bit canary, reduce the canary to 4 bytes with one byte being NUL to filter out string buffer overflow attacks. Signed-off-by: Glenn Washburn --- config.h.in | 2 ++ configure.ac | 20 grub-core/kern/efi/init.c | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/config.h.in b/config.h.in index 4d1e50eba79c..9b1d39971858 100644 --- a/config.h.in +++ b/config.h.in @@ -64,6 +64,8 @@ # define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" # define GRUB_PLATFORM "@GRUB_PLATFORM@" +# define GRUB_STACK_PROTECTOR_INIT @GRUB_STACK_PROTECTOR_INIT@ + # define RE_ENABLE_I18N 1 # define _GNU_SOURCE 1 diff --git a/configure.ac b/configure.ac index c19779c14d08..f15d31ec4c0e 100644 --- a/configure.ac +++ b/configure.ac @@ -1438,6 +1438,26 @@ else AC_MSG_ERROR([invalid value $enable_stack_protector for --enable-stack-protector]) fi TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DGRUB_STACK_PROTECTOR=1" + + if test -r /dev/urandom; then + # Generate the 8 byte stack protector canary at build time if /dev/urandom + # is able to be read. The first byte should be NUL to filter out string + # buffer overflow attacks. + GRUB_STACK_PROTECTOR_INIT="$($PYTHON -c 'import codecs; rf=open("/dev/urandom", "rb"); print("0x00"+codecs.encode(rf.read(7), "hex").decode("ascii"))')" + else +# Some hosts may not have a urandom (eg. Windows), so use statically +# generated random bytes +GRUB_STACK_PROTECTOR_INIT="0x00f2b7e2f193b25c" + fi + + if test x"$target_m32" = x1 ; then +# Make sure that the canary default value is 24-bits by only using the +# lower 3 bytes on 32 bit systems. This allows the upper byte to be NUL +# to filter out string buffer overflow attacks. +GRUB_STACK_PROTECTOR_INIT="0x00$(echo "$GRUB_STACK_PROTECTOR_INIT" | sed 's/.*\(..\)$/\1/')" + fi + + AC_SUBST([GRUB_STACK_PROTECTOR_INIT]) fi CFLAGS="$TARGET_CFLAGS" diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 08e24d46fad9..6c54af6e79e5 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -46,7 +46,7 @@ static grub_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID; static grub_efi_uint8_t stack_chk_guard_buf[32]; /* Initialize canary in case there is no RNG protocol. */ -grub_addr_t __stack_chk_guard = (grub_addr_t) 0x00f2b7e2f193b25c; +grub_addr_t __stack_chk_guard = (grub_addr_t) GRUB_STACK_PROTECTOR_INIT; void __attribute__ ((noreturn)) __stack_chk_fail (void) -- 2.34.1 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v3 0/3] efi: Initialize canary to non-zero value
Updates from v2: * Change NULL to NUL * Describe more why it is desirable to have a NUL byte in the canary Glenn Glenn Washburn (3): efi: Initialize canary to non-zero value efi: Generate stack protector canary at build time if urandom is available efi: Add support for reproducible builds config.h.in | 2 ++ configure.ac | 22 ++ grub-core/kern/efi/init.c | 3 ++- 3 files changed, 26 insertions(+), 1 deletion(-) Range-diff against v2: 1: a993f050ce89 ! 1: c4d3769d2c26 efi: Initialize canary to non-zero value @@ Commit message support the RNG protocol, then the canary will not be randomized and will be zero. This seems like a possibly easier value to write by an attacker. Initialize canary to static random bytes, so that it is still random when -there is no RNG protocol. Set at least one byte to NULL to protect against -string buffer overflow attacks. +there is no RNG protocol. Set at least one byte to NUL to protect against +string buffer overflow attacks. Code that writes NUL terminated strings +will terminate when a NUL is encountered in the input byte stream. So the +attacker will not be able to forge the canary by including it in the input +stream without terminating the string operation and thus limiting the +stack corruption. + +[1] https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage/ ## grub-core/kern/efi/init.c ## @@ grub-core/kern/efi/init.c: static grub_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID; 2: 177ae1cf1015 ! 2: 01a56aed2f26 efi: Generate stack protector canary at build time if urandom is available @@ Commit message Fallback to the statically generated random bytes if /dev/urandom is not readable (eg. Windows). -Reduce the canary to 3 bytes with a NULL upper byte on 32-bit architectures, -which use a 32-bit canary, to filter out string buffer overflow attacks. +On 32-bit architectures, which use a 32-bit canary, reduce the canary to 4 +bytes with one byte being NUL to filter out string buffer overflow attacks. ## config.h.in ## @@ @@ configure.ac: else + + if test -r /dev/urandom; then + # Generate the 8 byte stack protector canary at build time if /dev/urandom -+ # is able to be read. The first byte should be NULL to filter out string ++ # is able to be read. The first byte should be NUL to filter out string + # buffer overflow attacks. + GRUB_STACK_PROTECTOR_INIT="$($PYTHON -c 'import codecs; rf=open("/dev/urandom", "rb"); print("0x00"+codecs.encode(rf.read(7), "hex").decode("ascii"))')" + else @@ configure.ac: else + + if test x"$target_m32" = x1 ; then +# Make sure that the canary default value is 24-bits by only using the -+# lower 3 bytes on 32 bit systems. This allows the upper byte to be NULL ++# lower 3 bytes on 32 bit systems. This allows the upper byte to be NUL +# to filter out string buffer overflow attacks. +GRUB_STACK_PROTECTOR_INIT="0x00$(echo "$GRUB_STACK_PROTECTOR_INIT" | sed 's/.*\(..\)$/\1/')" + fi 3: c38fa7791697 ! 3: 5989c0102154 efi: Add support for reproducible builds @@ configure.ac: else + GRUB_STACK_PROTECTOR_INIT="0x00f2b7e2$(printf "%x" "$SOURCE_DATE_EPOCH" | sed 's/.*\(\)$/\1/')" + elif test -r /dev/urandom; then # Generate the 8 byte stack protector canary at build time if /dev/urandom - # is able to be read. The first byte should be NULL to filter out string + # is able to be read. The first byte should be NUL to filter out string # buffer overflow attacks. -- 2.34.1 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v3 1/3] efi: Initialize canary to non-zero value
The canary, __stack_chk_guard, is in the BSS and so will get initialized to zero if it is not explicitly initialized. If the UEFI firmware does not support the RNG protocol, then the canary will not be randomized and will be zero. This seems like a possibly easier value to write by an attacker. Initialize canary to static random bytes, so that it is still random when there is no RNG protocol. Set at least one byte to NUL to protect against string buffer overflow attacks. Code that writes NUL terminated strings will terminate when a NUL is encountered in the input byte stream. So the attacker will not be able to forge the canary by including it in the input stream without terminating the string operation and thus limiting the stack corruption. [1] https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage/ Signed-off-by: Glenn Washburn --- grub-core/kern/efi/init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index e759cc315b85..08e24d46fad9 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -45,7 +45,8 @@ static grub_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID; */ static grub_efi_uint8_t stack_chk_guard_buf[32]; -grub_addr_t __stack_chk_guard; +/* Initialize canary in case there is no RNG protocol. */ +grub_addr_t __stack_chk_guard = (grub_addr_t) 0x00f2b7e2f193b25c; void __attribute__ ((noreturn)) __stack_chk_fail (void) -- 2.34.1 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v3 3/3] efi: Add support for reproducible builds
Having randomly generated bytes in the binary output breaks reproducible builds. Since build timestamps are usually the source of irreproducibility there is a standard which defines an environment variable SOURCE_DATE_EPOCH to be used when set for build timestamps. According to the standard[1], the value of SOURCE_DATE_EPOCH is a base-10 integer of the number of seconds since the UNIX epoch. Currently, this is a 10 digit number that fits into 32-bits, but will not shortly after the year 2100. So to be future-proof only use the least significant 32-bits. On 64-bit architectures, where the canary is also 64-bits, there is an extra 32-bits that can be filled to provide more entropy. The first byte is null to filter out string buffer overflow attacks and the remaining 24-bits are set to static random bytes. [1] https://reproducible-builds.org/specs/source-date-epoch Signed-off-by: Glenn Washburn --- configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f15d31ec4c0e..0ba1cd71db00 100644 --- a/configure.ac +++ b/configure.ac @@ -1439,7 +1439,9 @@ else fi TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DGRUB_STACK_PROTECTOR=1" - if test -r /dev/urandom; then + if test -n "$SOURCE_DATE_EPOCH"; then + GRUB_STACK_PROTECTOR_INIT="0x00f2b7e2$(printf "%x" "$SOURCE_DATE_EPOCH" | sed 's/.*\(\)$/\1/')" + elif test -r /dev/urandom; then # Generate the 8 byte stack protector canary at build time if /dev/urandom # is able to be read. The first byte should be NUL to filter out string # buffer overflow attacks. -- 2.34.1 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 1/3] efi: Initialize canary to non-zero value
On Wed, 13 Dec 2023 21:24:07 +0100 Daniel Kiper wrote: > On Mon, Dec 11, 2023 at 01:27:48PM -0600, Glenn Washburn wrote: > > The canary, __stack_chk_guard, is in the BSS and so will get initialized to > > zero if it is not explicitly initialized. If the UEFI firmware does not > > support the RNG protocol, then the canary will not be randomized and will > > be zero. This seems like a possibly easier value to write by an attacker. > > Initialize canary to static random bytes, so that it is still random when > > there is no RNG protocol. Set at least one byte to NULL to protect against > > s/NULL/NUL/? If yes then please fix other places too. I've always written it as NULL which corresponds to the C macro, so it was not a typo. I don't really care though, so I'll make the change. > > string buffer overflow attacks. > > I think I can imagine how it works but instead of guessing I would > prefer to have this written down in the commit message. I'll make some additions. > Additionally, to have consistent behavior over the code I would zero out > highest order byte when they come from RNG too. I wasn't sure this was desirable for run-time random canaries. Adding a NULL byte decreases entropy of the canary while making canary forgery impossible in code that terminates on NULL. I'm thinking now that maybe it is desirable. An article from SANS[1] suggests indirectly that it should be used, especially if guessing the canary byte by byte can not be done (which seems to be true for the run-time random canary, but not the build-time canary). Another thing I'm just now thinking of is that a single NULL will not terminate UTF-16 strings, so we don't get protection of UTF-16 string operations. I haven't audited the code to determine if that might be a likely or common attack vector, nor have I seen this referenced in the literature, but it seems like it might be considering UEFI uses UTF-16 everywhere. Adding two NULL bytes might still provide enough entropy to make guessing the canary unlikely for 64-bit systems, but severely decreases the entropy on 32-bit systems. Maybe we really shouldn't care so much about 32-bit systems. > ... and it seems to me this will not work for big endian CPUs. > grub_be_to_cpu64_compile_time()? So I had mentioned previously about using grub_cpu_to_be64_compile_time() previously to have the NULL byte be in the lowest byte address of the in memory byte string representation of the canary. I had implemented this, but then realized that it does not work for GRUB's arm64 architecture. Arm64 uses BE-32[3] endian, which is word invariant, causing the upper and lower words to be swapped, but not the bytes within the words. So the in memory representation did not have the lowest byte address as NULL. This would require special macros, which I didn't care to add. Also, the macro will not compile on 64-bit architectures to initialize global variables (why is the 64-bit version not written like the 32 and 16-bit versions?). Its pretty trivial to fix the macro, but I didn't think that kind of change would be acceptable for the release. Furthermore, I now don't think it really matters which byte is NULL. If the attacker is exploiting a buffer overflow in a string operation that terminates on NULL, then a canary forgery is impossible no matter which byte of the canary is NULL. > Last but not least, I think it would be nice to have this feature > available on non-EFI platforms too. It would help us faster detect > various overwrites in the code which may slip through cracks. This seems like a good idea. Another idea, that's just come to me but I haven't seen discussed anywhere (probably because not much is focused on stack protection outside of the operating system) is falling back to a canary value based on a clock value if the RNG is not available. This would seem better than a build-time canary because it would be more difficult for the attacker to guess. > Anyway, I would want to have this patch set in the release. So, please > address first two comments ASAP (if nothing blows up again I want to > cut the release at the begging of next week). The other two things can > be addressed after the release. I count 5 distinct things. * s/NULL/NUL/ * More explanation in commit message * Add NUL byte to RNG created canary * use grub_be_to_cpu64_compile_time() * Add stack protection on non-EFI platforms Glenn > > Daniel [1] https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage/ [2] https://s3.eurecom.fr/docs/ifip18_bierbaumer.pdf#page=3 [3] https://stackoverflow.com/a/4287792 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel