From deeb72f8e7ae8bed01af6719730b282b72843040 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Stelmach?= Date: Fri, 9 Aug 2024 14:53:37 +0200 Subject: [PATCH] kdbus: Translate new u64-based kernel_cap_t to u32-based kdbus_caps MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- kernel/kdbus/metadata.c | 52 +++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/kernel/kdbus/metadata.c b/kernel/kdbus/metadata.c index 58cd85e..a9e819e 100644 --- a/kernel/kdbus/metadata.c +++ b/kernel/kdbus/metadata.c @@ -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 */ -- 2.34.1