- Fix file descriptor passing AGAIN. This has apparently been broken
on LP64 systems (and probably the SPARC) since the __cmsg_alignbytes() changes went in. - Change file descriptor passing to use CMSG_DATA(), not (cm + 1). This pretty much has to be done in order to make it work properly on LP64, and considering that it's been broken this long... - Use CMSG_SPACE() to determine the mbuf length needed for a given control message, and CMSG_LEN() to stash in the cmsg_len member.
This commit is contained in:
parent
d20c2ec7d2
commit
724a90318e
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: uipc_usrreq.c,v 1.46 2000/03/30 09:27:14 augustss Exp $ */
|
||||
/* $NetBSD: uipc_usrreq.c,v 1.47 2000/06/05 06:06:07 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -803,11 +803,15 @@ unp_externalize(rights)
|
|||
{
|
||||
struct proc *p = curproc; /* XXX */
|
||||
struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
|
||||
int i, *fdp = (int *)(cm + 1);
|
||||
int i, *fdp;
|
||||
struct file **rp;
|
||||
struct file *fp;
|
||||
int nfds = (cm->cmsg_len - ALIGN(sizeof(*cm))) / sizeof(struct file *);
|
||||
int f, error = 0;
|
||||
int nfds, f, error = 0;
|
||||
|
||||
nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) /
|
||||
sizeof(struct file *);
|
||||
fdp = (int *)CMSG_DATA(cm);
|
||||
rp = (struct file **)CMSG_DATA(cm);
|
||||
|
||||
/* Make sure the recipient should be able to see the descriptors.. */
|
||||
if (p->p_cwdi->cwdi_rdir != NULL) {
|
||||
|
@ -830,7 +834,7 @@ unp_externalize(rights)
|
|||
}
|
||||
}
|
||||
}
|
||||
rp = (struct file **)ALIGN(cm + 1);
|
||||
rp = (struct file **)CMSG_DATA(cm);
|
||||
|
||||
/* Make sure that the recipient has space */
|
||||
if (error || (!fdavail(p, nfds))) {
|
||||
|
@ -867,8 +871,8 @@ unp_externalize(rights)
|
|||
* Adjust length, in case of transition from large struct file
|
||||
* pointers to ints.
|
||||
*/
|
||||
cm->cmsg_len = sizeof(*cm) + (nfds * sizeof(int));
|
||||
rights->m_len = cm->cmsg_len;
|
||||
cm->cmsg_len = CMSG_LEN(nfds * sizeof(int));
|
||||
rights->m_len = CMSG_SPACE(nfds * sizeof(int));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -885,26 +889,14 @@ unp_internalize(control, p)
|
|||
int nfds;
|
||||
u_int neededspace;
|
||||
|
||||
/*
|
||||
* A VERY IMPORTANT NOTE ON THE USE OF sizeof(*cm) AS IT RELATES
|
||||
* TO SCM_RIGHTS MESSAGES!
|
||||
*
|
||||
* SCM_RIGHTS messages are an array of ints, which have 4-byte
|
||||
* alignment. A cmsghdr is a 12-byte long structure, so the
|
||||
* ints can be packed directly after the cmsghdr. When they
|
||||
* are converted to file *s, however, we must ALIGN() the
|
||||
* size of the cmsghdr, since pointers may be larger than ints,
|
||||
* and thus have more strict alignment requirements.
|
||||
*/
|
||||
|
||||
/* Sanity check the control message header */
|
||||
if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
|
||||
cm->cmsg_len != control->m_len)
|
||||
return (EINVAL);
|
||||
|
||||
/* Verify that the file descriptors are valid */
|
||||
nfds = (cm->cmsg_len - sizeof(*cm)) / sizeof(int);
|
||||
fdp = (int *)(cm + 1);
|
||||
nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) / sizeof(int);
|
||||
fdp = (int *)CMSG_DATA(cm);
|
||||
for (i = 0; i < nfds; i++) {
|
||||
fd = *fdp++;
|
||||
if ((unsigned)fd >= fdescp->fd_nfiles ||
|
||||
|
@ -914,9 +906,9 @@ unp_internalize(control, p)
|
|||
}
|
||||
|
||||
/* Make sure we have room for the struct file pointers */
|
||||
morespace:
|
||||
neededspace = (ALIGN(sizeof(*cm)) + nfds * sizeof(struct file *)) -
|
||||
control->m_len;
|
||||
morespace:
|
||||
neededspace = CMSG_SPACE(nfds * sizeof(struct file *)) -
|
||||
control->m_len;
|
||||
if (neededspace > M_TRAILINGSPACE(control)) {
|
||||
|
||||
/* if we already have a cluster, the message is just too big */
|
||||
|
@ -935,16 +927,16 @@ morespace:
|
|||
}
|
||||
|
||||
/* adjust message & mbuf to note amount of space actually used. */
|
||||
cm->cmsg_len += neededspace;
|
||||
control->m_len = cm->cmsg_len;
|
||||
cm->cmsg_len = CMSG_LEN(nfds * sizeof(struct file *));
|
||||
control->m_len = CMSG_SPACE(nfds * sizeof(struct file *));
|
||||
|
||||
/*
|
||||
* Transform the file descriptors into struct file pointers, in
|
||||
* reverse order so that if pointers are bigger than ints, the
|
||||
* int won't get until we're done.
|
||||
*/
|
||||
fdp = ((int *)(cm + 1)) + nfds - 1;
|
||||
rp = ((struct file **)ALIGN(cm + 1)) + nfds - 1;
|
||||
fdp = ((int *)CMSG_DATA(cm)) + nfds - 1;
|
||||
rp = ((struct file **)CMSG_DATA(cm)) + nfds - 1;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
fp = fdescp->fd_ofiles[*fdp--];
|
||||
FILE_USE(fp);
|
||||
|
@ -965,14 +957,15 @@ unp_addsockcred(p, control)
|
|||
struct cmsghdr *cmp;
|
||||
struct sockcred *sc;
|
||||
struct mbuf *m, *n;
|
||||
int len, i;
|
||||
int len, space, i;
|
||||
|
||||
len = sizeof(struct cmsghdr) + SOCKCREDSIZE(p->p_ucred->cr_ngroups);
|
||||
len = CMSG_LEN(SOCKCREDSIZE(p->p_ucred->cr_ngroups));
|
||||
space = CMSG_SPACE(SOCKCREDSIZE(p->p_ucred->cr_ngroups));
|
||||
|
||||
m = m_get(M_WAIT, MT_CONTROL);
|
||||
if (len > MLEN) {
|
||||
if (len > MCLBYTES)
|
||||
MEXTMALLOC(m, len, M_WAITOK);
|
||||
if (space > MLEN) {
|
||||
if (space > MCLBYTES)
|
||||
MEXTMALLOC(m, space, M_WAITOK);
|
||||
else
|
||||
MCLGET(m, M_WAIT);
|
||||
if ((m->m_flags & M_EXT) == 0) {
|
||||
|
@ -981,7 +974,7 @@ unp_addsockcred(p, control)
|
|||
}
|
||||
}
|
||||
|
||||
m->m_len = len;
|
||||
m->m_len = space;
|
||||
m->m_next = NULL;
|
||||
cmp = mtod(m, struct cmsghdr *);
|
||||
sc = (struct sockcred *)CMSG_DATA(cmp);
|
||||
|
|
Loading…
Reference in New Issue