Thread (15 messages) 15 messages, 3 authors, 4d ago

[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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help