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>