Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Nov 2020 20:01:21 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r367776 - in head: share/man/man4 sys/compat/linux sys/kern sys/sys
Message-ID:  <202011172001.0AHK1Le8019403@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Tue Nov 17 20:01:21 2020
New Revision: 367776
URL: https://svnweb.freebsd.org/changeset/base/367776

Log:
  unix(4): Enhance LOCAL_CREDS_PERSISTENT ABI
  
  As this ABI is still fresh (r367287), let's correct some mistakes now:
  
  - Version the structure to allow for future changes
  - Include sender's pid in control message structure
  - Use a distinct control message type from the cmsgcred / sockcred mess
  
  Discussed with:	kib, markj, trasz
  Differential Revision:	https://reviews.freebsd.org/D27084

Modified:
  head/share/man/man4/unix.4
  head/sys/compat/linux/linux_socket.c
  head/sys/kern/uipc_usrreq.c
  head/sys/sys/socket.h

Modified: head/share/man/man4/unix.4
==============================================================================
--- head/share/man/man4/unix.4	Tue Nov 17 19:56:47 2020	(r367775)
+++ head/share/man/man4/unix.4	Tue Nov 17 20:01:21 2020	(r367776)
@@ -28,7 +28,7 @@
 .\"     @(#)unix.4	8.1 (Berkeley) 6/9/93
 .\" $FreeBSD$
 .\"
-.Dd November 2, 2020
+.Dd November 9, 2020
 .Dt UNIX 4
 .Os
 .Sh NAME
@@ -295,6 +295,41 @@ except that socket credentials are passed on every rea
 or
 .Dv SOCK_SEQPACKET
 socket, instead of just the first read.
+Additionally, the
+.Va msg_control
+field in the
+.Vt msghdr
+structure points to a buffer that contains a
+.Vt cmsghdr
+structure followed by a variable length
+.Vt sockcred2
+structure, defined in
+.In sys/socket.h
+as follows:
+.Bd -literal
+struct sockcred2 {
+  int	sc_version;	/* version of this structure */
+  pid_t	sc_pid;		/* PID of sending process */
+  uid_t	sc_uid;		/* real user id */
+  uid_t	sc_euid;	/* effective user id */
+  gid_t	sc_gid;		/* real group id */
+  gid_t	sc_egid;	/* effective group id */
+  int	sc_ngroups;	/* number of supplemental groups */
+  gid_t	sc_groups[1];	/* variable length */
+};
+.Ed
+.Pp
+The current version is zero.
+.Pp
+The
+.Vt cmsghdr
+fields have the following values:
+.Bd -literal
+cmsg_len = CMSG_LEN(SOCKCRED2SIZE(ngroups))
+cmsg_level = SOL_SOCKET
+cmsg_type = SCM_CREDS2
+.Ed
+.Pp
 The
 .Dv LOCAL_CREDS
 and

Modified: head/sys/compat/linux/linux_socket.c
==============================================================================
--- head/sys/compat/linux/linux_socket.c	Tue Nov 17 19:56:47 2020	(r367775)
+++ head/sys/compat/linux/linux_socket.c	Tue Nov 17 20:01:21 2020	(r367776)
@@ -644,6 +644,8 @@ bsd_to_linux_cmsg_type(int cmsg_type)
 		return (LINUX_SCM_RIGHTS);
 	case SCM_CREDS:
 		return (LINUX_SCM_CREDENTIALS);
+	case SCM_CREDS2:
+		return (LINUX_SCM_CREDENTIALS);
 	case SCM_TIMESTAMP:
 		return (LINUX_SCM_TIMESTAMP);
 	}
@@ -1508,6 +1510,7 @@ linux_recvmsg_common(struct thread *td, l_int s, struc
 {
 	struct cmsghdr *cm;
 	struct cmsgcred *cmcred;
+	struct sockcred2 *scred;
 	struct l_cmsghdr *linux_cmsg = NULL;
 	struct l_ucred linux_ucred;
 	socklen_t datalen, maxlen, outlen;
@@ -1627,6 +1630,16 @@ linux_recvmsg_common(struct thread *td, l_int s, struc
 				linux_ucred.pid = cmcred->cmcred_pid;
 				linux_ucred.uid = cmcred->cmcred_uid;
 				linux_ucred.gid = cmcred->cmcred_gid;
+				data = &linux_ucred;
+				datalen = sizeof(linux_ucred);
+				break;
+
+			case SCM_CREDS2:
+				scred = data;
+				bzero(&linux_ucred, sizeof(linux_ucred));
+				linux_ucred.pid = scred->sc_pid;
+				linux_ucred.uid = scred->sc_uid;
+				linux_ucred.gid = scred->sc_gid;
 				data = &linux_ucred;
 				datalen = sizeof(linux_ucred);
 				break;

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c	Tue Nov 17 19:56:47 2020	(r367775)
+++ head/sys/kern/uipc_usrreq.c	Tue Nov 17 20:01:21 2020	(r367776)
@@ -308,7 +308,7 @@ static int	unp_internalize(struct mbuf **, struct thre
 static void	unp_internalize_fp(struct file *);
 static int	unp_externalize(struct mbuf *, struct mbuf **, int);
 static int	unp_externalize_fp(struct file *);
-static struct mbuf	*unp_addsockcred(struct thread *, struct mbuf *);
+static struct mbuf	*unp_addsockcred(struct thread *, struct mbuf *, int);
 static void	unp_process_defers(void * __unused, int);
 
 static void
@@ -1043,7 +1043,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m
 		}
 
 		if (unp2->unp_flags & UNP_WANTCRED_MASK)
-			control = unp_addsockcred(td, control);
+			control = unp_addsockcred(td, control,
+			    unp2->unp_flags);
 		if (unp->unp_addr != NULL)
 			from = (struct sockaddr *)unp->unp_addr;
 		else
@@ -1102,8 +1103,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m
 			 * SOCK_SEQPACKET (LOCAL_CREDS => WANTCRED_ONESHOT), or
 			 * forever (LOCAL_CREDS_PERSISTENT => WANTCRED_ALWAYS).
 			 */
+			control = unp_addsockcred(td, control, unp2->unp_flags);
 			unp2->unp_flags &= ~UNP_WANTCRED_ONESHOT;
-			control = unp_addsockcred(td, control);
 		}
 
 		/*
@@ -2383,34 +2384,58 @@ out:
 }
 
 static struct mbuf *
-unp_addsockcred(struct thread *td, struct mbuf *control)
+unp_addsockcred(struct thread *td, struct mbuf *control, int mode)
 {
 	struct mbuf *m, *n, *n_prev;
-	struct sockcred *sc;
 	const struct cmsghdr *cm;
-	int ngroups;
-	int i;
+	int ngroups, i, cmsgtype;
+	size_t ctrlsz;
 
 	ngroups = MIN(td->td_ucred->cr_ngroups, CMGROUP_MAX);
-	m = sbcreatecontrol(NULL, SOCKCREDSIZE(ngroups), SCM_CREDS, SOL_SOCKET);
+	if (mode & UNP_WANTCRED_ALWAYS) {
+		ctrlsz = SOCKCRED2SIZE(ngroups);
+		cmsgtype = SCM_CREDS2;
+	} else {
+		ctrlsz = SOCKCREDSIZE(ngroups);
+		cmsgtype = SCM_CREDS;
+	}
+
+	m = sbcreatecontrol(NULL, ctrlsz, cmsgtype, SOL_SOCKET);
 	if (m == NULL)
 		return (control);
 
-	sc = (struct sockcred *) CMSG_DATA(mtod(m, struct cmsghdr *));
-	sc->sc_uid = td->td_ucred->cr_ruid;
-	sc->sc_euid = td->td_ucred->cr_uid;
-	sc->sc_gid = td->td_ucred->cr_rgid;
-	sc->sc_egid = td->td_ucred->cr_gid;
-	sc->sc_ngroups = ngroups;
-	for (i = 0; i < sc->sc_ngroups; i++)
-		sc->sc_groups[i] = td->td_ucred->cr_groups[i];
+	if (mode & UNP_WANTCRED_ALWAYS) {
+		struct sockcred2 *sc;
 
+		sc = (void *)CMSG_DATA(mtod(m, struct cmsghdr *));
+		sc->sc_version = 0;
+		sc->sc_pid = td->td_proc->p_pid;
+		sc->sc_uid = td->td_ucred->cr_ruid;
+		sc->sc_euid = td->td_ucred->cr_uid;
+		sc->sc_gid = td->td_ucred->cr_rgid;
+		sc->sc_egid = td->td_ucred->cr_gid;
+		sc->sc_ngroups = ngroups;
+		for (i = 0; i < sc->sc_ngroups; i++)
+			sc->sc_groups[i] = td->td_ucred->cr_groups[i];
+	} else {
+		struct sockcred *sc;
+
+		sc = (void *)CMSG_DATA(mtod(m, struct cmsghdr *));
+		sc->sc_uid = td->td_ucred->cr_ruid;
+		sc->sc_euid = td->td_ucred->cr_uid;
+		sc->sc_gid = td->td_ucred->cr_rgid;
+		sc->sc_egid = td->td_ucred->cr_gid;
+		sc->sc_ngroups = ngroups;
+		for (i = 0; i < sc->sc_ngroups; i++)
+			sc->sc_groups[i] = td->td_ucred->cr_groups[i];
+	}
+
 	/*
 	 * Unlink SCM_CREDS control messages (struct cmsgcred), since just
 	 * created SCM_CREDS control message (struct sockcred) has another
 	 * format.
 	 */
-	if (control != NULL)
+	if (control != NULL && cmsgtype == SCM_CREDS)
 		for (n = control, n_prev = NULL; n != NULL;) {
 			cm = mtod(n, struct cmsghdr *);
     			if (cm->cmsg_level == SOL_SOCKET &&

Modified: head/sys/sys/socket.h
==============================================================================
--- head/sys/sys/socket.h	Tue Nov 17 19:56:47 2020	(r367775)
+++ head/sys/sys/socket.h	Tue Nov 17 20:01:21 2020	(r367776)
@@ -510,7 +510,7 @@ struct cmsgcred {
 };
 
 /*
- * Socket credentials.
+ * Socket credentials (LOCAL_CREDS).
  */
 struct sockcred {
 	uid_t	sc_uid;			/* real user id */
@@ -527,6 +527,22 @@ struct sockcred {
 #define	SOCKCREDSIZE(ngrps) \
 	(sizeof(struct sockcred) + (sizeof(gid_t) * ((ngrps) - 1)))
 
+/*
+ * Socket credentials (LOCAL_CREDS_PERSISTENT).
+ */
+struct sockcred2 {
+	int	sc_version;		/* version of this structure */
+	pid_t	sc_pid;			/* PID of sending process */
+	uid_t	sc_uid;			/* real user id */
+	uid_t	sc_euid;		/* effective user id */
+	gid_t	sc_gid;			/* real group id */
+	gid_t	sc_egid;		/* effective group id */
+	int	sc_ngroups;		/* number of supplemental groups */
+	gid_t	sc_groups[1];		/* variable length */
+};
+#define	SOCKCRED2SIZE(ngrps) \
+	(sizeof(struct sockcred2) + (sizeof(gid_t) * ((ngrps) - 1)))
+
 #endif /* __BSD_VISIBLE */
 
 /* given pointer to struct cmsghdr, return pointer to data */
@@ -571,6 +587,7 @@ struct sockcred {
 #define	SCM_REALTIME	0x05		/* timestamp (struct timespec) */
 #define	SCM_MONOTONIC	0x06		/* timestamp (struct timespec) */
 #define	SCM_TIME_INFO	0x07		/* timestamp info */
+#define	SCM_CREDS2	0x08		/* process creds (struct sockcred2) */
 
 struct sock_timestamp_info {
 	__uint32_t	st_info_flags;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202011172001.0AHK1Le8019403>