فهرست منبع

uClibc-ng: backport patch for riscv32 SSP problem

Waldemar Brodkorb 1 هفته پیش
والد
کامیت
20644a2c29
1فایلهای تغییر یافته به همراه184 افزوده شده و 0 حذف شده
  1. 184 0
      toolchain/uclibc-ng/patches/1.0.59/0001-Fix-SSP-support-for-riscv32.patch

+ 184 - 0
toolchain/uclibc-ng/patches/1.0.59/0001-Fix-SSP-support-for-riscv32.patch

@@ -0,0 +1,184 @@
+From 6d8ec52b8210caa850455fd3745b4873b5fead51 Mon Sep 17 00:00:00 2001
+From: Waldemar Brodkorb <wbx@openadk.org>
+Date: Sat, 15 Aug 2026 18:20:33 +0200
+Subject: [PATCH] Fix SSP support for riscv32
+
+On modern 32-bit architectures like RISC-V (riscv32), legacy 32-bit
+time syscalls like __NR_gettimeofday are intentionally omitted because
+RV32 implements a strict time64-only ABI to avoid the Year 2038 bug.
+
+Therefore, use AT_RANDOM from the auxiliary vector first, as glibc does,
+to obtain random data for the stack canary. If AT_RANDOM is unavailable,
+fall back to reading random data from /dev/urandom.
+
+Tested with aarch64, riscv32 and riscv32 noMMU targets.
+
+Co-developed-by: Charles Mirabile <cmirabil@redhat.com>
+---
+ extra/Configs/Config.in               | 10 -----
+ ldso/include/dl-syscall.h             | 12 ------
+ ldso/ldso/ldso.c                      |  4 +-
+ libc/misc/internals/__uClibc_main.c   |  4 +-
+ libc/sysdeps/linux/common/dl-osinfo.h | 58 ++++++++++++++++-----------
+ 5 files changed, 41 insertions(+), 47 deletions(-)
+
+diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
+index c3aabf1b4..15a072593 100644
+--- a/extra/Configs/Config.in
++++ b/extra/Configs/Config.in
+@@ -2211,16 +2211,6 @@ config UCLIBC_HAS_SSP
+ 
+ 	  Most people will answer N.
+ 
+-config SSP_QUICK_CANARY
+-	bool "Use simple guard values without accessing /dev/urandom"
+-	depends on UCLIBC_HAS_SSP
+-	help
+-	  Use gettimeofday(2) to define the __guard without accessing
+-	  /dev/urandom.
+-	  WARNING: This makes smashing stack protector vulnerable to timing
+-	  	attacks.
+-	  Most people will answer N.
+-
+ choice
+ 	prompt "Propolice protection blocking signal"
+ 	depends on UCLIBC_HAS_SSP
+diff --git a/ldso/include/dl-syscall.h b/ldso/include/dl-syscall.h
+index c143b8d45..e08b2cd41 100644
+--- a/ldso/include/dl-syscall.h
++++ b/ldso/include/dl-syscall.h
+@@ -260,18 +260,6 @@ _dl_pread(int fd, void *buf, size_t count, off_t offset)
+ }
+ #endif
+ 
+-#ifdef __UCLIBC_HAS_SSP__
+-# include <sys/time.h>
+-# define __NR__dl_gettimeofday __NR_gettimeofday
+-static __always_inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv,
+-# ifdef __USE_BSD
+-                        struct timezone *
+-# else
+-                        void *
+-# endif
+-						, tz)
+-#endif
+-
+ /* Some architectures always use 12 as page shift for mmap2() eventhough the
+  * real PAGE_SHIFT != 12.  Other architectures use the same value as
+  * PAGE_SHIFT...
+diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
+index 55f7d7e45..96ee3d496 100755
+--- a/ldso/ldso/ldso.c
++++ b/ldso/ldso/ldso.c
+@@ -1225,7 +1225,9 @@ of this helper program; chances are you did not intend to run this program.\n\
+ #ifdef __UCLIBC_HAS_SSP__
+ 	_dl_debug_early("Setting up SSP guards\n");
+ 	/* Set up the stack checker's canary.  */
+-	stack_chk_guard = _dl_setup_stack_chk_guard ();
++	stack_chk_guard = _dl_setup_stack_chk_guard (
++		_dl_auxvt[AT_RANDOM].a_type == AT_RANDOM ?
++		(void *)_dl_auxvt[AT_RANDOM].a_un.a_val : NULL);
+ # ifdef THREAD_SET_STACK_GUARD
+ 	THREAD_SET_STACK_GUARD (stack_chk_guard);
+ # else
+diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c
+index 549606505..bbf471b17 100644
+--- a/libc/misc/internals/__uClibc_main.c
++++ b/libc/misc/internals/__uClibc_main.c
+@@ -296,7 +296,9 @@ void __uClibc_init(void)
+ #ifndef SHARED
+ # ifdef __UCLIBC_HAS_SSP__
+     /* Set up the stack checker's canary.  */
+-    stack_chk_guard = _dl_setup_stack_chk_guard();
++    stack_chk_guard = _dl_setup_stack_chk_guard(
++    _dl_auxvt[AT_RANDOM].a_type == AT_RANDOM ?
++        (void *)_dl_auxvt[AT_RANDOM].a_un.a_val : NULL);
+ #  ifdef THREAD_SET_STACK_GUARD
+     THREAD_SET_STACK_GUARD (stack_chk_guard);
+ #  else
+diff --git a/libc/sysdeps/linux/common/dl-osinfo.h b/libc/sysdeps/linux/common/dl-osinfo.h
+index 3110cb05d..0a3e2ce53 100644
+--- a/libc/sysdeps/linux/common/dl-osinfo.h
++++ b/libc/sysdeps/linux/common/dl-osinfo.h
+@@ -21,43 +21,55 @@
+ #  ifdef IS_IN_libc
+ #   include <fcntl.h>
+ #   include <unistd.h>
+-#   include <sys/time.h>
++#   include <string.h>
+ #   define OPEN open
+ #   define READ read
+ #   define CLOSE close
+-#   define GETTIMEOFDAY gettimeofday
++#   define MEMCPY memcpy
+ #  else
++#   include <dl-string.h>
+ #   define OPEN _dl_open
+ #   define READ _dl_read
+ #   define CLOSE _dl_close
+-#   define GETTIMEOFDAY _dl_gettimeofday
++#   define MEMCPY _dl_memcpy
+ #  endif
+ 
+-static __always_inline uintptr_t _dl_setup_stack_chk_guard(void)
++static __always_inline uintptr_t
++_dl_setup_stack_chk_guard(void *dl_random)
+ {
+-	uintptr_t ret;
+-#  ifndef __SSP_QUICK_CANARY__
+-	{
++	/* Fallback just the "terminator canary". */
++	uintptr_t ret = 0xFF0A0D00UL;
++
++	/*
++	 * Linux supplies random data through AT_RANDOM.
++	 * Use it directly when available.
++	 */
++	if (dl_random != NULL) {
++		MEMCPY(&ret, dl_random, sizeof(ret));
++	} else {
+ 		int fd = OPEN("/dev/urandom", O_RDONLY, 0);
+-		if (fd >= 0) {
+-			size_t size = READ(fd, &ret, sizeof(ret));
+-			CLOSE(fd);
+-			if (size == (size_t) sizeof(ret))
+-				return ret;
+-		}
++		if (fd < 0)
++			goto out;
++		uintptr_t tmp;
++		size_t size = READ(fd, &tmp, sizeof(tmp));
++		CLOSE(fd);
++		if (size != sizeof(tmp))
++			goto out;
++		ret = tmp;
+ 	}
+-#  endif /* !__SSP_QUICK_CANARY__ */
++out:
+ 
+-	/* Start with the "terminator canary". */
+-	ret = 0xFF0A0D00UL;
++/* Make it harder to leak the canary by ensuring
++ * that the byte with the lowest address is a zero
++ * byte that will stop a rogue strcpy, printf %s, etc*/
++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
++	ret &= ~(uintptr_t)0xff;
++#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
++	ret &= ~((uintptr_t)0xff << (8 * (sizeof(ret) - 1)));
++#else
++# error "Unknown byte order"
++#endif
+ 
+-	/* Everything failed? Or we are using a weakened model of the
+-	 * terminator canary */
+-	{
+-		struct timeval tv;
+-		if (GETTIMEOFDAY(&tv, NULL) != (-1))
+-			ret ^= tv.tv_usec ^ tv.tv_sec;
+-	}
+ 	return ret;
+ }
+ # endif /* libc || rtld */
+-- 
+2.47.3
+