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-all
mailing list