ff6046
From 401f1fdc309175d3920c0fe168e52c601474c000 Mon Sep 17 00:00:00 2001
ff6046
From: Lennart Poettering <lennart@poettering.net>
ff6046
Date: Wed, 10 Oct 2018 11:07:54 +0200
ff6046
Subject: [PATCH] capability: introduce CAP_TO_MASK_CORRECTED() macro replacing
ff6046
 CAP_TO_MASK()
ff6046
ff6046
linux/capability.h's CAP_TO_MASK potentially shifts a signed int "1"
ff6046
(i.e. 32bit wide) left by 31 which means it becomes negative. That's
ff6046
just weird, and ubsan complains about it. Let's introduce our own macro
ff6046
CAP_TO_MASK_CORRECTED which doesn't fall into this trap, and make use of
ff6046
it.
ff6046
ff6046
Fixes: #10347
ff6046
(cherry picked from commit 5f00c5684f96c93a22840f7241ee444b9a632b1e)
ff6046
ff6046
Resolves: #1683319
ff6046
---
ff6046
 src/basic/capability-util.h       | 4 ++++
ff6046
 src/libsystemd/sd-bus/bus-creds.c | 2 +-
ff6046
 2 files changed, 5 insertions(+), 1 deletion(-)
ff6046
ff6046
diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h
ff6046
index 4a4a86093a..59591d4b52 100644
ff6046
--- a/src/basic/capability-util.h
ff6046
+++ b/src/basic/capability-util.h
ff6046
@@ -39,3 +39,7 @@ static inline bool cap_test_all(uint64_t caps) {
ff6046
 }
ff6046
 
ff6046
 bool ambient_capabilities_supported(void);
ff6046
+
ff6046
+/* Identical to linux/capability.h's CAP_TO_MASK(), but uses an unsigned 1U instead of a signed 1 for shifting left, in
ff6046
+ * order to avoid complaints about shifting a signed int left by 31 bits, which would make it negative. */
ff6046
+#define CAP_TO_MASK_CORRECTED(x) (1U << ((x) & 31U))
ff6046
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
ff6046
index aae9fcd58b..b180a033b8 100644
ff6046
--- a/src/libsystemd/sd-bus/bus-creds.c
ff6046
+++ b/src/libsystemd/sd-bus/bus-creds.c
ff6046
@@ -663,7 +663,7 @@ static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
ff6046
 
ff6046
         sz = DIV_ROUND_UP(cap_last_cap(), 32U);
ff6046
 
ff6046
-        return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
ff6046
+        return !!(c->capability[offset * sz + CAP_TO_INDEX((uint32_t) capability)] & CAP_TO_MASK_CORRECTED((uint32_t) capability));
ff6046
 }
ff6046
 
ff6046
 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {