capability: introduce CAP_TO_MASK_CORRECTED() macro replacing CAP_TO_MASK()
authorLennart Poettering <lennart@poettering.net>
Wed, 10 Oct 2018 09:07:54 +0000 (11:07 +0200)
committerLukáš Nykrýn <lnykryn@redhat.com>
Fri, 3 May 2019 11:00:29 +0000 (13:00 +0200)
linux/capability.h's CAP_TO_MASK potentially shifts a signed int "1"
(i.e. 32bit wide) left by 31 which means it becomes negative. That's
just weird, and ubsan complains about it. Let's introduce our own macro
CAP_TO_MASK_CORRECTED which doesn't fall into this trap, and make use of
it.

Fixes: #10347
(cherry picked from commit 5f00c5684f96c93a22840f7241ee444b9a632b1e)

Resolves: #1683319

src/basic/capability-util.h
src/libsystemd/sd-bus/bus-creds.c

index 4a4a86093a4b94756fb4ec94dc900bbecf0f4d04..59591d4b521eb56039b11a0bf62d0eae2f410e90 100644 (file)
@@ -39,3 +39,7 @@ static inline bool cap_test_all(uint64_t caps) {
 }
 
 bool ambient_capabilities_supported(void);
+
+/* Identical to linux/capability.h's CAP_TO_MASK(), but uses an unsigned 1U instead of a signed 1 for shifting left, in
+ * order to avoid complaints about shifting a signed int left by 31 bits, which would make it negative. */
+#define CAP_TO_MASK_CORRECTED(x) (1U << ((x) & 31U))
index aae9fcd58b41e4abec848547cb468a3d01a40ba9..b180a033b85263b6337302bedd06609c7c583d1d 100644 (file)
@@ -663,7 +663,7 @@ static int has_cap(sd_bus_creds *c, unsigned offset, int capability) {
 
         sz = DIV_ROUND_UP(cap_last_cap(), 32U);
 
-        return !!(c->capability[offset * sz + CAP_TO_INDEX(capability)] & CAP_TO_MASK(capability));
+        return !!(c->capability[offset * sz + CAP_TO_INDEX((uint32_t) capability)] & CAP_TO_MASK_CORRECTED((uint32_t) capability));
 }
 
 _public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) {