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
This commit is contained in:
parent
b1976ea14c
commit
ede4af47ae
@ -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 read from a
|
||||
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
|
||||
|
@ -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, struct l_msghdr *msghdr,
|
||||
{
|
||||
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;
|
||||
@ -1631,6 +1634,16 @@ linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
|
||||
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;
|
||||
|
||||
case SCM_TIMESTAMP:
|
||||
if (datalen != sizeof(struct timeval)) {
|
||||
error = EMSGSIZE;
|
||||
|
@ -308,7 +308,7 @@ static int unp_internalize(struct mbuf **, struct thread *);
|
||||
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, struct sockaddr *nam,
|
||||
}
|
||||
|
||||
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, struct sockaddr *nam,
|
||||
* 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 @@ unp_internalize(struct mbuf **controlp, struct thread *td)
|
||||
}
|
||||
|
||||
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 &&
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user