- 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:
thorpej 2000-06-05 06:06:07 +00:00
parent d20c2ec7d2
commit 724a90318e
1 changed files with 28 additions and 35 deletions

View File

@ -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);