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

Reply via email to