svn commit: r367287 - in head: share/man/man4 sys/kern sys/sys

Conrad Meyer cem at FreeBSD.org
Tue Nov 3 01:17:46 UTC 2020


Author: cem
Date: Tue Nov  3 01:17:45 2020
New Revision: 367287
URL: https://svnweb.freebsd.org/changeset/base/367287

Log:
  unix(4): Add SOL_LOCAL:LOCAL_CREDS_PERSISTENT
  
  This option is intended to be semantically identical to Linux's
  SOL_SOCKET:SO_PASSCRED.  For now, it is mutually exclusive with the
  pre-existing sockopt SOL_LOCAL:LOCAL_CREDS.
  
  Reviewed by:	markj (penultimate version)
  Differential Revision:	https://reviews.freebsd.org/D27011

Modified:
  head/share/man/man4/unix.4
  head/sys/kern/uipc_usrreq.c
  head/sys/sys/un.h
  head/sys/sys/unpcb.h

Modified: head/share/man/man4/unix.4
==============================================================================
--- head/share/man/man4/unix.4	Tue Nov  3 01:10:27 2020	(r367286)
+++ head/share/man/man4/unix.4	Tue Nov  3 01:17:45 2020	(r367287)
@@ -28,7 +28,7 @@
 .\"     @(#)unix.4	8.1 (Berkeley) 6/9/93
 .\" $FreeBSD$
 .\"
-.Dd August 3, 2020
+.Dd November 2, 2020
 .Dt UNIX 4
 .Os
 .Sh NAME
@@ -201,7 +201,7 @@ which can be set with
 .Xr setsockopt 2
 and tested with
 .Xr getsockopt 2 :
-.Bl -tag -width ".Dv LOCAL_CONNWAIT"
+.Bl -tag -width ".Dv LOCAL_CREDS_PERSISTENT"
 .It Dv LOCAL_CREDS
 This option may be enabled on
 .Dv SOCK_DGRAM ,
@@ -287,6 +287,19 @@ such as error messages.
 Therefore, a message accompanied by a particular
 .Fa sc_euid
 value should not be trusted as being from that user.
+.It Dv LOCAL_CREDS_PERSISTENT
+This option is similar to
+.Dv LOCAL_CREDS ,
+except that socket credentials are passed on every read from a
+.Dv SOCK_STREAM
+or
+.Dv SOCK_SEQPACKET
+socket, instead of just the first read.
+The
+.Dv LOCAL_CREDS
+and
+.Dv LOCAL_CREDS_PERSISTENT
+options are mutually exclusive.
 .It Dv LOCAL_CONNWAIT
 Used with
 .Dv SOCK_STREAM

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c	Tue Nov  3 01:10:27 2020	(r367286)
+++ head/sys/kern/uipc_usrreq.c	Tue Nov  3 01:17:45 2020	(r367287)
@@ -1040,7 +1040,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m
 			break;
 		}
 
-		if (unp2->unp_flags & UNP_WANTCRED)
+		if (unp2->unp_flags & UNP_WANTCRED_MASK)
 			control = unp_addsockcred(td, control);
 		if (unp->unp_addr != NULL)
 			from = (struct sockaddr *)unp->unp_addr;
@@ -1094,12 +1094,13 @@ uipc_send(struct socket *so, int flags, struct mbuf *m
 			break;
 		}
 		SOCKBUF_LOCK(&so2->so_rcv);
-		if (unp2->unp_flags & UNP_WANTCRED) {
+		if (unp2->unp_flags & UNP_WANTCRED_MASK) {
 			/*
-			 * Credentials are passed only once on SOCK_STREAM
-			 * and SOCK_SEQPACKET.
+			 * Credentials are passed only once on SOCK_STREAM and
+			 * SOCK_SEQPACKET (LOCAL_CREDS => WANTCRED_ONESHOT), or
+			 * forever (LOCAL_CREDS_PERSISTENT => WANTCRED_ALWAYS).
 			 */
-			unp2->unp_flags &= ~UNP_WANTCRED;
+			unp2->unp_flags &= ~UNP_WANTCRED_ONESHOT;
 			control = unp_addsockcred(td, control);
 		}
 
@@ -1405,10 +1406,16 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt
 
 		case LOCAL_CREDS:
 			/* Unlocked read. */
-			optval = unp->unp_flags & UNP_WANTCRED ? 1 : 0;
+			optval = unp->unp_flags & UNP_WANTCRED_ONESHOT ? 1 : 0;
 			error = sooptcopyout(sopt, &optval, sizeof(optval));
 			break;
 
+		case LOCAL_CREDS_PERSISTENT:
+			/* Unlocked read. */
+			optval = unp->unp_flags & UNP_WANTCRED_ALWAYS ? 1 : 0;
+			error = sooptcopyout(sopt, &optval, sizeof(optval));
+			break;
+
 		case LOCAL_CONNWAIT:
 			/* Unlocked read. */
 			optval = unp->unp_flags & UNP_CONNWAIT ? 1 : 0;
@@ -1424,28 +1431,38 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt
 	case SOPT_SET:
 		switch (sopt->sopt_name) {
 		case LOCAL_CREDS:
+		case LOCAL_CREDS_PERSISTENT:
 		case LOCAL_CONNWAIT:
 			error = sooptcopyin(sopt, &optval, sizeof(optval),
 					    sizeof(optval));
 			if (error)
 				break;
 
-#define	OPTSET(bit) do {						\
+#define	OPTSET(bit, exclusive) do {					\
 	UNP_PCB_LOCK(unp);						\
-	if (optval)							\
-		unp->unp_flags |= bit;					\
-	else								\
-		unp->unp_flags &= ~bit;					\
+	if (optval) {							\
+		if ((unp->unp_flags & (exclusive)) != 0) {		\
+			UNP_PCB_UNLOCK(unp);				\
+			error = EINVAL;					\
+			break;						\
+		}							\
+		unp->unp_flags |= (bit);				\
+	} else								\
+		unp->unp_flags &= ~(bit);				\
 	UNP_PCB_UNLOCK(unp);						\
 } while (0)
 
 			switch (sopt->sopt_name) {
 			case LOCAL_CREDS:
-				OPTSET(UNP_WANTCRED);
+				OPTSET(UNP_WANTCRED_ONESHOT, UNP_WANTCRED_ALWAYS);
 				break;
 
+			case LOCAL_CREDS_PERSISTENT:
+				OPTSET(UNP_WANTCRED_ALWAYS, UNP_WANTCRED_ONESHOT);
+				break;
+
 			case LOCAL_CONNWAIT:
-				OPTSET(UNP_CONNWAIT);
+				OPTSET(UNP_CONNWAIT, 0);
 				break;
 
 			default:
@@ -1651,8 +1668,7 @@ unp_copy_peercred(struct thread *td, struct unpcb *cli
 	memcpy(&server_unp->unp_peercred, &listen_unp->unp_peercred,
 	    sizeof(server_unp->unp_peercred));
 	server_unp->unp_flags |= UNP_HAVEPC;
-	if (listen_unp->unp_flags & UNP_WANTCRED)
-		client_unp->unp_flags |= UNP_WANTCRED;
+	client_unp->unp_flags |= (listen_unp->unp_flags & UNP_WANTCRED_MASK);
 }
 
 static int
@@ -2853,8 +2869,12 @@ db_print_unpflags(int unp_flags)
 		db_printf("%sUNP_HAVEPC", comma ? ", " : "");
 		comma = 1;
 	}
-	if (unp_flags & UNP_WANTCRED) {
-		db_printf("%sUNP_WANTCRED", comma ? ", " : "");
+	if (unp_flags & UNP_WANTCRED_ALWAYS) {
+		db_printf("%sUNP_WANTCRED_ALWAYS", comma ? ", " : "");
+		comma = 1;
+	}
+	if (unp_flags & UNP_WANTCRED_ONESHOT) {
+		db_printf("%sUNP_WANTCRED_ONESHOT", comma ? ", " : "");
 		comma = 1;
 	}
 	if (unp_flags & UNP_CONNWAIT) {

Modified: head/sys/sys/un.h
==============================================================================
--- head/sys/sys/un.h	Tue Nov  3 01:10:27 2020	(r367286)
+++ head/sys/sys/un.h	Tue Nov  3 01:17:45 2020	(r367287)
@@ -67,6 +67,7 @@ struct sockaddr_un {
 /* Socket options. */
 #define	LOCAL_PEERCRED		1	/* retrieve peer credentials */
 #define	LOCAL_CREDS		2	/* pass credentials to receiver */
+#define	LOCAL_CREDS_PERSISTENT	3	/* pass credentials to receiver */
 #define	LOCAL_CONNWAIT		4	/* connects block until accepted */
 
 /* Start of reserved space for third-party socket options. */

Modified: head/sys/sys/unpcb.h
==============================================================================
--- head/sys/sys/unpcb.h	Tue Nov  3 01:10:27 2020	(r367286)
+++ head/sys/sys/unpcb.h	Tue Nov  3 01:17:45 2020	(r367287)
@@ -107,9 +107,12 @@ struct unpcb {
  * to determine whether the contents should be sent to the user or
  * not.
  */
-#define UNP_HAVEPC			0x001
-#define	UNP_WANTCRED			0x004	/* credentials wanted */
+#define	UNP_HAVEPC			0x001
+#define	UNP_WANTCRED_ALWAYS		0x002	/* credentials wanted always */
+#define	UNP_WANTCRED_ONESHOT		0x004	/* credentials wanted once */
 #define	UNP_CONNWAIT			0x008	/* connect blocks until accepted */
+
+#define	UNP_WANTCRED_MASK	(UNP_WANTCRED_ONESHOT | UNP_WANTCRED_ALWAYS)
 
 /*
  * These flags are used to handle non-atomicity in connect() and bind()


More information about the svn-src-head mailing list