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()
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to