kdbus: Translate new u64-based kernel_cap_t to u32-based kdbus_caps 36/315936/2 accepted/tizen_unified_dev accepted/tizen/unified/20240812.190117 accepted/tizen/unified/dev/20240812.223246 accepted/tizen/unified/x/20240813.112412
authorŁukasz Stelmach <l.stelmach@samsung.com>
Fri, 9 Aug 2024 12:53:37 +0000 (14:53 +0200)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Fri, 9 Aug 2024 14:31:08 +0000 (16:31 +0200)
Using kernel_cap_t in kdbus_meta_caps changes the alignment of userland
facing structures which breaks userland code trying to parse the structure
sent in kdbus header. Translate kernel_cap_t to u32 similarly to what's
done in capget(2).

Change-Id: I8c21746dca2972cbc0ad48dfea4dba2216c0669c
Ref: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f122a08b197d076ccf136c73fae0146875812a88
Fixes: e59920a ("kdbus: use u64 capability for v6.3 or later version")
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
kernel/kdbus/metadata.c

index 58cd85e265e933a86eba340fb66f8ffb1a1a453a..a9e819ee722bf64383699a1563253355d24b1835 100644 (file)
@@ -128,16 +128,18 @@ struct kdbus_meta_conn {
        char *conn_description;
 };
 
+/* The macros has been missing since 6.3 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
+#define _KERNEL_CAPABILITY_U32S         2
+#define CAP_LAST_U32_VALID_MASK         (CAP_TO_MASK(CAP_LAST_CAP + 1) -1)
+#endif
+
 /* fixed size equivalent of "kdbus_caps" */
 struct kdbus_meta_caps {
        u32 last_cap;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
-       kernel_cap_t cap_sets[4];
-#else
        struct {
                u32 caps[_KERNEL_CAPABILITY_U32S];
        } set[4];
-#endif
 };
 
 /**
@@ -771,25 +773,35 @@ static void kdbus_meta_export_caps(struct kdbus_meta_caps *out,
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
        if (parent) {
-               out->cap_sets[0] = cred->cap_inheritable;
-               out->cap_sets[1] = cred->cap_permitted;
-               out->cap_sets[2] = cred->cap_effective;
-               out->cap_sets[3] = cred->cap_bset;
+               out->set[0].caps[0] = cred->cap_inheritable.val;
+               out->set[0].caps[1] = cred->cap_inheritable.val >> 32;
+               out->set[1].caps[0] = cred->cap_permitted.val;
+               out->set[1].caps[1] = cred->cap_permitted.val >> 32;
+               out->set[2].caps[0] = cred->cap_effective.val;
+               out->set[2].caps[1] = cred->cap_effective.val >> 32;
+               out->set[3].caps[0] = cred->cap_bset.val;
+               out->set[3].caps[1] = cred->cap_bset.val >> 32;
        } else if (owner) {
-               out->cap_sets[0] = CAP_EMPTY_SET;
-               out->cap_sets[1] = CAP_FULL_SET;
-               out->cap_sets[2] = CAP_FULL_SET;
-               out->cap_sets[3] = CAP_FULL_SET;
+               out->set[0].caps[0] = CAP_EMPTY_SET.val;
+               out->set[0].caps[1] = CAP_EMPTY_SET.val >> 32;
+               out->set[1].caps[0] = CAP_FULL_SET.val;
+               out->set[1].caps[1] = CAP_FULL_SET.val >> 32;
+               out->set[2].caps[0] = CAP_FULL_SET.val;
+               out->set[2].caps[1] = CAP_FULL_SET.val >> 32;
+               out->set[3].caps[0] = CAP_FULL_SET.val;
+               out->set[3].caps[1] = CAP_FULL_SET.val >> 32;
+
        } else {
-               out->cap_sets[0] = CAP_EMPTY_SET;
-               out->cap_sets[1] = CAP_EMPTY_SET;
-               out->cap_sets[2] = CAP_EMPTY_SET;
-               out->cap_sets[3] = CAP_EMPTY_SET;
+               out->set[0].caps[0] = CAP_EMPTY_SET.val;
+               out->set[0].caps[1] = CAP_EMPTY_SET.val >> 32;
+               out->set[1].caps[0] = CAP_EMPTY_SET.val;
+               out->set[1].caps[1] = CAP_EMPTY_SET.val >> 32;
+               out->set[2].caps[0] = CAP_EMPTY_SET.val;
+               out->set[2].caps[1] = CAP_EMPTY_SET.val >> 32;
+               out->set[3].caps[0] = CAP_EMPTY_SET.val;
+               out->set[3].caps[1] = CAP_EMPTY_SET.val >> 32;
        }
 
-       /* clear unused bits */
-       for (i = 0; i < 4; i++)
-               out->cap_sets[i].val &= CAP_VALID_MASK;
 #else
        CAP_FOR_EACH_U32(i) {
                if (parent) {
@@ -810,11 +822,11 @@ static void kdbus_meta_export_caps(struct kdbus_meta_caps *out,
                }
        }
 
+#endif
        /* clear unused bits */
        for (i = 0; i < 4; i++)
                out->set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
                                        CAP_LAST_U32_VALID_MASK;
-#endif
 }
 
 /* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */