[RFC PATCH 06/41] netlink: keep classic sender ids in skb->cb
flat view
COOLING4d
From: Jan Koester <hidden>
Date: 2026-10-18 18:01:54
Also in:
keyrings, linux-api, linux-arch, linux-cifs, linux-ext4, linux-fsdevel, linux-nfs, lkml, netdev
Subsystem:
driver core, kobjects, debugfs and sysfs, library code, networking [general], the rest · Maintainers:
Greg Kroah-Hartman, "Rafael J. Wysocki", Danilo Krummrich, Johan Hovold, Andrew Morton, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
netlink_skb_parms has to fit into skb->cb, and netlink skbs are cloned together with it for broadcasts, so there is neither room for kuid_t and kgid_t holding UUIDs nor a single owner for an allocation. Store the sender ids as classic kernel ids: a UUID or GUID becomes -1, which reaches the receiver of SCM_CREDENTIALS as the overflow id. The kernel's own permission checks on netlink messages use the socket's file credentials, not these. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Jan Koester <redacted> --- include/linux/netlink.h | 2 +- include/net/scm.h | 28 ++++++++++++++++++++++++++++ lib/kobject_uevent.c | 8 ++++---- net/netlink/af_netlink.c | 4 ++-- 4 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 882e9c1b6c..999c7a352e 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h@@ -23,7 +23,7 @@ enum netlink_skb_flags { }; struct netlink_skb_parms { - struct scm_creds creds; /* Skb credentials */ + struct scm_creds_classic creds; /* Skb credentials */ __u32 portid; __u32 dst_group; __u32 flags;
diff --git a/include/net/scm.h b/include/net/scm.h
index 86ae6bc109..daa52e3d44 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h@@ -23,6 +23,34 @@ struct scm_creds { kgid_t gid; }; +/* + * Sender credentials for skb->cb of skbs that get cloned along with it + * (netlink, bluetooth): no room for kuid_t and kgid_t, and no single owner + * for an allocation. The ids are classic kernel ids; a UUID or GUID becomes + * -1, which the receiver of SCM_CREDENTIALS sees as the overflow id. + */ +struct scm_creds_classic { + u32 pid; + uid_t uid; + gid_t gid; +}; + +static inline void scm_creds_to_classic(struct scm_creds_classic *classic, + const struct scm_creds *creds) +{ + classic->pid = creds->pid; + classic->uid = __kuid_val(creds->uid); + classic->gid = __kgid_val(creds->gid); +} + +static inline void scm_creds_from_classic(struct scm_creds *creds, + const struct scm_creds_classic *classic) +{ + creds->pid = classic->pid; + creds->uid = KUIDT_INIT(classic->uid); + creds->gid = KGIDT_INIT(classic->gid); +} + #ifdef CONFIG_UNIX struct unix_edge; #endif
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index ddbc4d7482..8b63044881 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c@@ -297,8 +297,8 @@ static struct sk_buff *alloc_uevent_skb(struct kobj_uevent_env *env, skb_put_data(skb, env->buf, env->buflen); parms = &NETLINK_CB(skb); - parms->creds.uid = GLOBAL_ROOT_UID; - parms->creds.gid = GLOBAL_ROOT_GID; + parms->creds.uid = __kuid_val(GLOBAL_ROOT_UID); + parms->creds.gid = __kgid_val(GLOBAL_ROOT_GID); parms->dst_group = 1; parms->portid = 0;
@@ -362,12 +362,12 @@ static int uevent_net_broadcast_tagged(struct sock *usk, /* fix uid */ root_uid = make_kuid(owning_user_ns, 0); if (uid_valid(root_uid)) - parms->creds.uid = root_uid; + parms->creds.uid = __kuid_val(root_uid); /* fix gid */ root_gid = make_kgid(owning_user_ns, 0); if (gid_valid(root_gid)) - parms->creds.gid = root_gid; + parms->creds.gid = __kgid_val(root_gid); } ret = netlink_broadcast(usk, skb, 0, 1, GFP_KERNEL);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 3029894eda..282a5d0da4 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c@@ -1901,7 +1901,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) NETLINK_CB(skb).portid = nlk->portid; NETLINK_CB(skb).dst_group = dst_group; - NETLINK_CB(skb).creds = scm.creds; + scm_creds_to_classic(&NETLINK_CB(skb).creds, &scm.creds); NETLINK_CB(skb).flags = netlink_skb_flags; err = -EFAULT;
@@ -1994,7 +1994,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, netlink_cmsg_listen_all_nsid(sk, msg, skb); memset(&scm, 0, sizeof(scm)); - scm.creds = *NETLINK_CREDS(skb); + scm_creds_from_classic(&scm.creds, NETLINK_CREDS(skb)); if (flags & MSG_TRUNC) copied = data_skb->len;
--
2.56.0