git: c10d567ea022 - main - include: de-macro __ssp_overlap(), improve semantics and checking

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sat, 13 Jul 2024 05:22:59 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=c10d567ea022de8705fb23f8563c4726f2d09ca0

commit c10d567ea022de8705fb23f8563c4726f2d09ca0
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2024-07-13 05:16:10 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-07-13 05:16:23 +0000

    include: de-macro __ssp_overlap(), improve semantics and checking
    
    Switch away from pointer arithmetic to provide more obvious semantics
    for checking overlap on pointer ranges.  This lets us remove some casts
    that need not exist and removes some possible fragility in its use.
    
    While we're here, check for overflow just in case; sometimes we use a
    caller-supplied size if __builtin_object_size(3) can't deduce the buffer
    size, and we should fail the check if the size is nonsensical for the
    provided buffers.
    
    Reviewed by:    markj
    Sponsored by:   Klara, Inc.
    Sponsored by:   Stormshield
---
 include/ssp/ssp.h            | 19 +++++++++++++------
 lib/libc/secure/memcpy_chk.c |  2 +-
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/include/ssp/ssp.h b/include/ssp/ssp.h
index 622e9e901ba6..de109da4959e 100644
--- a/include/ssp/ssp.h
+++ b/include/ssp/ssp.h
@@ -83,12 +83,19 @@ __ssp_inline rtype fun args { \
 #define __ssp_redirect0(rtype, fun, args, call) \
     __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos0)
 
-/*
- * Take caution when using __ssp_overlap!  Don't use it in contexts where we
- * can end up with double-evaluation of a statement with some side-effects.
- */
-#define __ssp_overlap(a, b, l) \
-    (((a) <= (b) && (b) < (a) + (l)) || ((b) <= (a) && (a) < (b) + (l)))
+#include <machine/_stdint.h>
+
+static inline int
+__ssp_overlap(const void *leftp, const void *rightp, __size_t sz)
+{
+	__uintptr_t left = (__uintptr_t)leftp;
+	__uintptr_t right = (__uintptr_t)rightp;
+
+	if (left <= right)
+		return (SIZE_MAX - sz < left || right < left + sz);
+
+	return (SIZE_MAX - sz < right || left < right + sz);
+}
 
 __BEGIN_DECLS
 void __stack_chk_fail(void) __dead2;
diff --git a/lib/libc/secure/memcpy_chk.c b/lib/libc/secure/memcpy_chk.c
index 2a269cb475ab..ac995d00ee8c 100644
--- a/lib/libc/secure/memcpy_chk.c
+++ b/lib/libc/secure/memcpy_chk.c
@@ -44,7 +44,7 @@ __memcpy_chk(void * __restrict dst, const void * __restrict src, size_t len,
 	if (len > slen)
 		__chk_fail();
 
-	if (__ssp_overlap((const char *)src, (const char *)dst, len))
+	if (__ssp_overlap(src, dst, len))
 		__chk_fail();
 
 	return (memcpy(dst, src, len));