Blob Blame History Raw
From 09405ba91c40e4e08f2212c946a432fa001d04bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
Date: Thu, 1 Jul 2021 20:06:22 +0200
Subject: [PATCH] libsepol: ignore UBSAN false-positives
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Unsigned integer overflow is well-defined and not undefined behavior.
But it is still useful to enable undefined behavior sanitizer checks on
unsigned arithmetic to detect possible issues on counters or variables
with similar purpose.

Annotate functions, in which unsigned overflows are expected to happen,
with the respective Clang function attribute[1].
GCC does not support sanitizing unsigned integer arithmetic[2].

    avtab.c:76:2: runtime error: unsigned integer overflow: 6 * 3432918353 cannot be represented in type 'unsigned int'
    policydb.c:795:42: runtime error: unsigned integer overflow: 8160943042179512010 * 11 cannot be represented in type 'unsigned long'
    symtab.c:25:12: runtime error: left shift of 1766601759 by 4 places cannot be represented in type 'unsigned int'

[1]: https://clang.llvm.org/docs/AttributeReference.html#no-sanitize
[2]: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 libsepol/src/avtab.c    |  1 +
 libsepol/src/policydb.c |  1 +
 libsepol/src/private.h  | 11 +++++++++++
 libsepol/src/symtab.c   |  4 ++++
 4 files changed, 17 insertions(+)

diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c
index 5e16a0e9899e..93505b20e4c0 100644
--- a/libsepol/src/avtab.c
+++ b/libsepol/src/avtab.c
@@ -52,6 +52,7 @@
 /* Based on MurmurHash3, written by Austin Appleby and placed in the
  * public domain.
  */
+ignore_unsigned_overflow_
 static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
 {
 	static const uint32_t c1 = 0xcc9e2d51;
diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
index 0398ceed2574..7093d9b7028a 100644
--- a/libsepol/src/policydb.c
+++ b/libsepol/src/policydb.c
@@ -789,6 +789,7 @@ static int roles_init(policydb_t * p)
 	goto out;
 }
 
+ignore_unsigned_overflow_
 static inline unsigned long
 partial_name_hash(unsigned long c, unsigned long prevhash)
 {
diff --git a/libsepol/src/private.h b/libsepol/src/private.h
index c63238abe5f3..71287282fbc0 100644
--- a/libsepol/src/private.h
+++ b/libsepol/src/private.h
@@ -49,6 +49,17 @@
 
 #define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b)))
 
+/* Use to ignore intentional unsigned under- and overflows while running under UBSAN. */
+#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 4)
+#if (__clang_major__ >= 12)
+#define ignore_unsigned_overflow_        __attribute__((no_sanitize("unsigned-integer-overflow", "unsigned-shift-base")))
+#else
+#define ignore_unsigned_overflow_        __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#else
+#define ignore_unsigned_overflow_
+#endif
+
 /* Policy compatibility information. */
 struct policydb_compat_info {
 	unsigned int type;
diff --git a/libsepol/src/symtab.c b/libsepol/src/symtab.c
index 9a417ca24b53..a60618510bd3 100644
--- a/libsepol/src/symtab.c
+++ b/libsepol/src/symtab.c
@@ -8,9 +8,13 @@
  */
 
 #include <string.h>
+
+#include "private.h"
+
 #include <sepol/policydb/hashtab.h>
 #include <sepol/policydb/symtab.h>
 
+ignore_unsigned_overflow_
 static unsigned int symhash(hashtab_t h, const_hashtab_key_t key)
 {
 	const char *p, *keyp;
-- 
2.32.0