diff options
author | dwmalone <dwmalone@FreeBSD.org> | 2001-10-04 13:11:48 +0000 |
---|---|---|
committer | dwmalone <dwmalone@FreeBSD.org> | 2001-10-04 13:11:48 +0000 |
commit | 86cf053ae0113e103de743ed432880fb2b462149 (patch) | |
tree | 6615cc44c88feefec804ce8ebb7cd6284b4483b6 | |
parent | a41aa2f6cfba0d70cf320783974b86c4bb644eda (diff) | |
download | FreeBSD-src-86cf053ae0113e103de743ed432880fb2b462149.zip FreeBSD-src-86cf053ae0113e103de743ed432880fb2b462149.tar.gz |
Hopefully improve control message passing over Unix domain sockets.
1) Allow the sending of more than one control message at a time
over a unix domain socket. This should cover the PR 29499.
2) This requires that unp_{ex,in}ternalize and unp_scan understand
mbufs with more than one control message at a time.
3) Internalize and externalize used to work on the mbuf in-place.
This made life quite complicated and the code for sizeof(int) <
sizeof(file *) could end up doing the wrong thing. The patch always
create a new mbuf/cluster now. This resulted in the change of the
prototype for the domain externalise function.
4) You can now send SCM_TIMESTAMP messages.
5) Always use CMSG_DATA(cm) to determine the start where the data
in unp_{ex,in}ternalize. It was using ((struct cmsghdr *)cm + 1)
in some places, which gives the wrong alignment on the alpha.
(NetBSD made this fix some time ago).
This results in an ABI change for discriptor passing and creds
passing on the alpha. (Probably on the IA64 and Spare ports too).
6) Fix userland programs to use CMSG_* macros too.
7) Be more careful about freeing mbufs containing (file *)s.
This is made possible by the prototype change of externalise.
PR: 29499
MFC after: 6 weeks
-rw-r--r-- | lib/libc/rpc/clnt_vc.c | 16 | ||||
-rw-r--r-- | lib/libc/rpc/svc_vc.c | 23 | ||||
-rw-r--r-- | sbin/mount_portalfs/activate.c | 8 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 27 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 437 | ||||
-rw-r--r-- | sys/netgraph/ng_socket.c | 4 | ||||
-rw-r--r-- | sys/sys/domain.h | 2 | ||||
-rw-r--r-- | sys/sys/un.h | 2 | ||||
-rw-r--r-- | usr.sbin/mount_portalfs/activate.c | 8 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.c | 10 |
10 files changed, 320 insertions, 217 deletions
diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c index 6cdaad1..d2d0178 100644 --- a/lib/libc/rpc/clnt_vc.c +++ b/lib/libc/rpc/clnt_vc.c @@ -793,7 +793,10 @@ __msgread(sock, buf, cnt) { struct iovec iov[1]; struct msghdr msg; - struct cmessage cm; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(struct cmsgcred))]; + } cm; bzero((char *)&cm, sizeof(cm)); iov[0].iov_base = buf; @@ -804,7 +807,7 @@ __msgread(sock, buf, cnt) msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = (caddr_t)&cm; - msg.msg_controllen = sizeof(struct cmessage); + msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred)); msg.msg_flags = 0; return(_recvmsg(sock, &msg, 0)); @@ -818,7 +821,10 @@ __msgwrite(sock, buf, cnt) { struct iovec iov[1]; struct msghdr msg; - struct cmessage cm; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(struct cmsgcred))]; + } cm; bzero((char *)&cm, sizeof(cm)); iov[0].iov_base = buf; @@ -826,14 +832,14 @@ __msgwrite(sock, buf, cnt) cm.cmsg.cmsg_type = SCM_CREDS; cm.cmsg.cmsg_level = SOL_SOCKET; - cm.cmsg.cmsg_len = sizeof(struct cmessage); + cm.cmsg.cmsg_len = CMSG_LEN(sizeof(struct cmsgcred)); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = (caddr_t)&cm; - msg.msg_controllen = sizeof(struct cmessage); + msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred)); msg.msg_flags = 0; return(_sendmsg(sock, &msg, 0)); diff --git a/lib/libc/rpc/svc_vc.c b/lib/libc/rpc/svc_vc.c index 052678b..95b907a 100644 --- a/lib/libc/rpc/svc_vc.c +++ b/lib/libc/rpc/svc_vc.c @@ -400,8 +400,6 @@ read_vc(xprtp, buf, len) struct pollfd pollfd; struct sockaddr *sa; struct cmessage *cm; - struct cmsghdr *cmp; - struct sockcred *sc; xprt = (SVCXPRT *)(void *)xprtp; assert(xprt != NULL); @@ -429,9 +427,7 @@ read_vc(xprtp, buf, len) if (sa->sa_family == AF_LOCAL) { cm = (struct cmessage *)xprt->xp_verf.oa_base; if ((len = __msgread_withcred(sock, buf, len, cm)) > 0) { - cmp = &cm->cmsg; - sc = (struct sockcred *)(void *)CMSG_DATA(cmp); - xprt->xp_p2 = sc; + xprt->xp_p2 = &cm->cmcred; return (len); } } else { @@ -638,8 +634,14 @@ __msgread_withcred(sock, buf, cnt, cmp) { struct iovec iov[1]; struct msghdr msg; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(struct cmsgcred))]; + } cm; + int ret; + - bzero(cmp, sizeof(*cmp)); + bzero(&cm, sizeof(cm)); iov[0].iov_base = buf; iov[0].iov_len = cnt; @@ -647,11 +649,14 @@ __msgread_withcred(sock, buf, cnt, cmp) msg.msg_iovlen = 1; msg.msg_name = NULL; msg.msg_namelen = 0; - msg.msg_control = cmp; - msg.msg_controllen = sizeof(struct cmessage); + msg.msg_control = &cm; + msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred)); msg.msg_flags = 0; - return(_recvmsg(sock, &msg, 0)); + ret = _recvmsg(sock, &msg, 0); + bcopy(&cm.cmsg, &cmp->cmsg, sizeof(cmp->cmsg)); + bcopy(CMSG_DATA(&cm), &cmp->cmcred, sizeof(cmp->cmcred)); + return ret; } static int diff --git a/sbin/mount_portalfs/activate.c b/sbin/mount_portalfs/activate.c index 5646498..6143620 100644 --- a/sbin/mount_portalfs/activate.c +++ b/sbin/mount_portalfs/activate.c @@ -113,9 +113,9 @@ int error; int n; struct iovec iov; struct msghdr msg; - struct { + union { struct cmsghdr cmsg; - int fd; + char control[CMSG_SPACE(sizeof(int))]; } ctl; /* @@ -137,10 +137,10 @@ int error; * construct a suitable rights control message. */ if (fd >= 0) { - ctl.fd = fd; - ctl.cmsg.cmsg_len = sizeof(ctl); + ctl.cmsg.cmsg_len = CMSG_LEN(sizeof(int)); ctl.cmsg.cmsg_level = SOL_SOCKET; ctl.cmsg.cmsg_type = SCM_RIGHTS; + *((int *)CMSG_DATA(&ctl.cmsg)) = fd; msg.msg_control = (caddr_t) &ctl; msg.msg_controllen = ctl.cmsg.cmsg_len; } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index a54dcff..0b40522 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -672,7 +672,7 @@ soreceive(so, psa, uio, mp0, controlp, flagsp) struct mbuf **controlp; int *flagsp; { - register struct mbuf *m, **mp; + struct mbuf *m, **mp; register int flags, len, error, s, offset; struct protosw *pr = so->so_proto; struct mbuf *nextrecord; @@ -798,23 +798,22 @@ dontblock: m = m->m_next; } else { sbfree(&so->so_rcv, m); - if (controlp) { - if (pr->pr_domain->dom_externalize && - mtod(m, struct cmsghdr *)->cmsg_type == - SCM_RIGHTS) - error = (*pr->pr_domain->dom_externalize)(m); + so->so_rcv.sb_mb = m->m_next; + m->m_next = NULL; + if (pr->pr_domain->dom_externalize) + error = + (*pr->pr_domain->dom_externalize)(m, controlp); + else if (controlp) *controlp = m; - so->so_rcv.sb_mb = m->m_next; - m->m_next = 0; - m = so->so_rcv.sb_mb; - } else { - MFREE(m, so->so_rcv.sb_mb); - m = so->so_rcv.sb_mb; - } + else + m_freem(m); + m = so->so_rcv.sb_mb; } if (controlp) { orig_resid = 0; - controlp = &(*controlp)->m_next; + do + controlp = &(*controlp)->m_next; + while (*controlp != NULL); } } if (m) { diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 52c60cf..7480773 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -90,7 +90,8 @@ static void unp_gc __P((void)); static void unp_scan __P((struct mbuf *, void (*)(struct file *))); static void unp_mark __P((struct file *)); static void unp_discard __P((struct file *)); -static int unp_internalize __P((struct mbuf *, struct thread *)); +static void unp_freerights __P((struct file **, int)); +static int unp_internalize __P((struct mbuf **, struct thread *)); static int unp_listen __P((struct unpcb *, struct proc *)); static int @@ -274,7 +275,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, goto release; } - if (control && (error = unp_internalize(control, td))) + if (control && (error = unp_internalize(&control, td))) goto release; switch (so->so_type) { @@ -952,80 +953,127 @@ unp_drain() } #endif +static void +unp_freerights(rp, fdcount) + struct file **rp; + int fdcount; +{ + int i; + struct file *fp; + + for (i = 0; i < fdcount; i++) { + fp = *rp; + /* + * zero the pointer before calling + * unp_discard since it may end up + * in unp_gc().. + */ + *rp++ = 0; + unp_discard(fp); + } +} + int -unp_externalize(rights) - struct mbuf *rights; +unp_externalize(control, controlp) + struct mbuf *control, **controlp; { struct thread *td = curthread; /* XXX */ - register int i; - register struct cmsghdr *cm = mtod(rights, struct cmsghdr *); - register int *fdp; - register struct file **rp; - register struct file *fp; - int newfds = (cm->cmsg_len - (CMSG_DATA(cm) - (u_char *)cm)) - / sizeof (struct file *); + struct cmsghdr *cm = mtod(control, struct cmsghdr *); + int i; + int *fdp; + struct file **rp; + struct file *fp; + void *data; + socklen_t clen = control->m_len, datalen; + int error, newfds; int f; + u_int newlen; - /* - * if the new FD's will not fit, then we free them all - */ - if (!fdavail(td, newfds)) { - rp = (struct file **)CMSG_DATA(cm); - for (i = 0; i < newfds; i++) { - fp = *rp; + error = 0; + if (controlp != NULL) /* controlp == NULL => free control messages */ + *controlp = NULL; + + while (cm != NULL) { + if (sizeof(*cm) > clen || cm->cmsg_len > clen) { + error = EINVAL; + break; + } + + data = CMSG_DATA(cm); + datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; + + if (cm->cmsg_level == SOL_SOCKET + && cm->cmsg_type == SCM_RIGHTS) { + newfds = datalen / sizeof(struct file *); + rp = data; + + /* If we're not outputting the discriptors free them. */ + if (error || controlp == NULL) { + unp_freerights(rp, newfds); + goto next; + } + /* if the new FD's will not fit free them. */ + if (!fdavail(td, newfds)) { + error = EMSGSIZE; + unp_freerights(rp, newfds); + goto next; + } /* - * zero the pointer before calling unp_discard, - * since it may end up in unp_gc().. + * now change each pointer to an fd in the global + * table to an integer that is the index to the + * local fd table entry that we set up to point + * to the global one we are transferring. */ - *rp++ = 0; - unp_discard(fp); - } - return (EMSGSIZE); - } - /* - * now change each pointer to an fd in the global table to - * an integer that is the index to the local fd table entry - * that we set up to point to the global one we are transferring. - * If sizeof (struct file *) is bigger than or equal to sizeof int, - * then do it in forward order. In that case, an integer will - * always come in the same place or before its corresponding - * struct file pointer. - * If sizeof (struct file *) is smaller than sizeof int, then - * do it in reverse order. - */ - if (sizeof (struct file *) >= sizeof (int)) { - fdp = (int *)(cm + 1); - rp = (struct file **)CMSG_DATA(cm); - for (i = 0; i < newfds; i++) { - if (fdalloc(td, 0, &f)) - panic("unp_externalize"); - fp = *rp++; - td->td_proc->p_fd->fd_ofiles[f] = fp; - fp->f_msgcount--; - unp_rights--; - *fdp++ = f; + newlen = newfds * sizeof(int); + *controlp = sbcreatecontrol(NULL, newlen, + SCM_RIGHTS, SOL_SOCKET); + if (*controlp == NULL) { + error = E2BIG; + unp_freerights(rp, newfds); + goto next; + } + + fdp = (int *) + CMSG_DATA(mtod(*controlp, struct cmsghdr *)); + for (i = 0; i < newfds; i++) { + if (fdalloc(td, 0, &f)) + panic("unp_externalize fdalloc failed"); + fp = *rp++; + td->td_proc->p_fd->fd_ofiles[f] = fp; + fp->f_msgcount--; + unp_rights--; + *fdp++ = f; + } + } else { /* We can just copy anything else across */ + if (error || controlp == NULL) + goto next; + *controlp = sbcreatecontrol(NULL, datalen, + cm->cmsg_type, cm->cmsg_level); + if (*controlp == NULL) { + error = ENOBUFS; + goto next; + } + bcopy(data, + CMSG_DATA(mtod(*controlp, struct cmsghdr *)), + datalen); } - } else { - fdp = (int *)(cm + 1) + newfds - 1; - rp = (struct file **)CMSG_DATA(cm) + newfds - 1; - for (i = 0; i < newfds; i++) { - if (fdalloc(td, 0, &f)) - panic("unp_externalize"); - fp = *rp--; - td->td_proc->p_fd->fd_ofiles[f] = fp; - fp->f_msgcount--; - unp_rights--; - *fdp-- = f; + + controlp = &(*controlp)->m_next; + +next: + if (CMSG_SPACE(datalen) < clen) { + clen -= CMSG_SPACE(datalen); + cm = (struct cmsghdr *) + ((caddr_t)cm + CMSG_SPACE(datalen)); + } else { + clen = 0; + cm = NULL; } } - /* - * Adjust length, in case sizeof(struct file *) and sizeof(int) - * differs. - */ - cm->cmsg_len = CMSG_LEN(newfds * sizeof(int)); - rights->m_len = cm->cmsg_len; - return (0); + m_freem(control); + + return (error); } void @@ -1043,109 +1091,134 @@ unp_init(void) #endif static int -unp_internalize(control, td) - struct mbuf *control; +unp_internalize(controlp, td) + struct mbuf **controlp; struct thread *td; { + struct mbuf *control = *controlp; struct proc *p = td->td_proc; struct filedesc *fdescp = p->p_fd; - register struct cmsghdr *cm = mtod(control, struct cmsghdr *); - register struct file **rp; - register struct file *fp; - register int i, fd, *fdp; - register struct cmsgcred *cmcred; - int oldfds; + struct cmsghdr *cm = mtod(control, struct cmsghdr *); + struct cmsgcred *cmcred; + struct file **rp; + struct file *fp; + struct timeval *tv; + int i, fd, *fdp; + void *data; + socklen_t clen = control->m_len, datalen; + int error, oldfds; u_int newlen; - if ((cm->cmsg_type != SCM_RIGHTS && cm->cmsg_type != SCM_CREDS) || - cm->cmsg_level != SOL_SOCKET || cm->cmsg_len != control->m_len) - return (EINVAL); + error = 0; + *controlp = NULL; - /* - * Fill in credential information. - */ - if (cm->cmsg_type == SCM_CREDS) { - cmcred = (struct cmsgcred *)(cm + 1); - cmcred->cmcred_pid = p->p_pid; - cmcred->cmcred_uid = p->p_ucred->cr_ruid; - cmcred->cmcred_gid = p->p_ucred->cr_rgid; - cmcred->cmcred_euid = p->p_ucred->cr_uid; - cmcred->cmcred_ngroups = MIN(p->p_ucred->cr_ngroups, + while (cm != NULL) { + if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET + || cm->cmsg_len > clen) { + error = EINVAL; + goto out; + } + + data = CMSG_DATA(cm); + datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; + + switch (cm->cmsg_type) { + /* + * Fill in credential information. + */ + case SCM_CREDS: + *controlp = sbcreatecontrol(NULL, sizeof(*cmcred), + SCM_CREDS, SOL_SOCKET); + if (*controlp == NULL) { + error = ENOBUFS; + goto out; + } + + cmcred = (struct cmsgcred *) + CMSG_DATA(mtod(*controlp, struct cmsghdr *)); + cmcred->cmcred_pid = p->p_pid; + cmcred->cmcred_uid = p->p_ucred->cr_ruid; + cmcred->cmcred_gid = p->p_ucred->cr_rgid; + cmcred->cmcred_euid = p->p_ucred->cr_uid; + cmcred->cmcred_ngroups = MIN(p->p_ucred->cr_ngroups, CMGROUP_MAX); - for (i = 0; i < cmcred->cmcred_ngroups; i++) - cmcred->cmcred_groups[i] = p->p_ucred->cr_groups[i]; - return(0); - } + for (i = 0; i < cmcred->cmcred_ngroups; i++) + cmcred->cmcred_groups[i] = + p->p_ucred->cr_groups[i]; + break; - oldfds = (cm->cmsg_len - sizeof (*cm)) / sizeof (int); - /* - * check that all the FDs passed in refer to legal OPEN files - * If not, reject the entire operation. - */ - fdp = (int *)(cm + 1); - for (i = 0; i < oldfds; i++) { - fd = *fdp++; - if ((unsigned)fd >= fdescp->fd_nfiles || - fdescp->fd_ofiles[fd] == NULL) - return (EBADF); - } - /* - * Now replace the integer FDs with pointers to - * the associated global file table entry.. - * Allocate a bigger buffer as necessary. But if an cluster is not - * enough, return E2BIG. - */ - newlen = CMSG_LEN(oldfds * sizeof(struct file *)); - if (newlen > MCLBYTES) - return (E2BIG); - if (newlen - control->m_len > M_TRAILINGSPACE(control)) { - if (control->m_flags & M_EXT) - return (E2BIG); - MCLGET(control, M_TRYWAIT); - if ((control->m_flags & M_EXT) == 0) - return (ENOBUFS); - - /* copy the data to the cluster */ - memcpy(mtod(control, char *), cm, cm->cmsg_len); - cm = mtod(control, struct cmsghdr *); - } + case SCM_RIGHTS: + oldfds = datalen / sizeof (int); + /* + * check that all the FDs passed in refer to legal files + * If not, reject the entire operation. + */ + fdp = data; + for (i = 0; i < oldfds; i++) { + fd = *fdp++; + if ((unsigned)fd >= fdescp->fd_nfiles || + fdescp->fd_ofiles[fd] == NULL) { + error = EBADF; + goto out; + } + } + /* + * Now replace the integer FDs with pointers to + * the associated global file table entry.. + */ + newlen = oldfds * sizeof(struct file *); + *controlp = sbcreatecontrol(NULL, newlen, + SCM_RIGHTS, SOL_SOCKET); + if (*controlp == NULL) { + error = E2BIG; + goto out; + } - /* - * Adjust length, in case sizeof(struct file *) and sizeof(int) - * differs. - */ - control->m_len = cm->cmsg_len = newlen; + fdp = data; + rp = (struct file **) + CMSG_DATA(mtod(*controlp, struct cmsghdr *)); + for (i = 0; i < oldfds; i++) { + fp = fdescp->fd_ofiles[*fdp++]; + *rp++ = fp; + fp->f_count++; + fp->f_msgcount++; + unp_rights++; + } + break; - /* - * Transform the file descriptors into struct file pointers. - * If sizeof (struct file *) is bigger than or equal to sizeof int, - * then do it in reverse order so that the int won't get until - * we're done. - * If sizeof (struct file *) is smaller than sizeof int, then - * do it in forward order. - */ - if (sizeof (struct file *) >= sizeof (int)) { - fdp = (int *)(cm + 1) + oldfds - 1; - rp = (struct file **)CMSG_DATA(cm) + oldfds - 1; - for (i = 0; i < oldfds; i++) { - fp = fdescp->fd_ofiles[*fdp--]; - *rp-- = fp; - fp->f_count++; - fp->f_msgcount++; - unp_rights++; + case SCM_TIMESTAMP: + *controlp = sbcreatecontrol(NULL, sizeof(*tv), + SCM_TIMESTAMP, SOL_SOCKET); + if (*controlp == NULL) { + error = ENOBUFS; + goto out; + } + tv = (struct timeval *) + CMSG_DATA(mtod(*controlp, struct cmsghdr *)); + microtime(tv); + break; + + default: + error = EINVAL; + goto out; } - } else { - fdp = (int *)(cm + 1); - rp = (struct file **)CMSG_DATA(cm); - for (i = 0; i < oldfds; i++) { - fp = fdescp->fd_ofiles[*fdp++]; - *rp++ = fp; - fp->f_count++; - fp->f_msgcount++; - unp_rights++; + + controlp = &(*controlp)->m_next; + + if (CMSG_SPACE(datalen) < clen) { + clen -= CMSG_SPACE(datalen); + cm = (struct cmsghdr *) + ((caddr_t)cm + CMSG_SPACE(datalen)); + } else { + clen = 0; + cm = NULL; } } - return (0); + +out: + m_freem(control); + + return (error); } static int unp_defer, unp_gcing; @@ -1343,28 +1416,48 @@ unp_scan(m0, op) register struct mbuf *m0; void (*op) __P((struct file *)); { - register struct mbuf *m; - register struct file **rp; - register struct cmsghdr *cm; - register int i; + struct mbuf *m; + struct file **rp; + struct cmsghdr *cm; + void *data; + int i; + socklen_t clen, datalen; int qfds; while (m0) { - for (m = m0; m; m = m->m_next) - if (m->m_type == MT_CONTROL && - m->m_len >= sizeof(*cm)) { - cm = mtod(m, struct cmsghdr *); - if (cm->cmsg_level != SOL_SOCKET || - cm->cmsg_type != SCM_RIGHTS) - continue; - qfds = (cm->cmsg_len - - (CMSG_DATA(cm) - (u_char *)cm)) - / sizeof (struct file *); - rp = (struct file **)CMSG_DATA(cm); - for (i = 0; i < qfds; i++) - (*op)(*rp++); - break; /* XXX, but saves time */ + for (m = m0; m; m = m->m_next) { + if (m->m_type == MT_CONTROL) + continue; + + cm = mtod(m, struct cmsghdr *); + clen = m->m_len; + + while (cm != NULL) { + if (sizeof(*cm) > clen || cm->cmsg_len > clen) + break; + + data = CMSG_DATA(cm); + datalen = (caddr_t)cm + cm->cmsg_len + - (caddr_t)data; + + if (cm->cmsg_level == SOL_SOCKET && + cm->cmsg_type == SCM_RIGHTS) { + qfds = datalen / sizeof (struct file *); + rp = data; + for (i = 0; i < qfds; i++) + (*op)(*rp++); + } + + if (CMSG_SPACE(datalen) < clen) { + clen -= CMSG_SPACE(datalen); + cm = (struct cmsghdr *) + ((caddr_t)cm + CMSG_SPACE(datalen)); + } else { + clen = 0; + cm = NULL; + } } + } m0 = m0->m_act; } } diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c index a7e7e20..87924ce 100644 --- a/sys/netgraph/ng_socket.c +++ b/sys/netgraph/ng_socket.c @@ -583,7 +583,7 @@ ng_internalize(struct mbuf *control, struct thread *td) } /* Check there is only one FD. XXX what would more than one signify? */ - oldfds = (cm->cmsg_len - sizeof(*cm)) / sizeof(int); + oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int); if (oldfds != 1) { TRAP_ERROR; return (EINVAL); @@ -591,7 +591,7 @@ ng_internalize(struct mbuf *control, struct thread *td) /* Check that the FD given is legit. and change it to a pointer to a * struct file. */ - fd = *(int *) (cm + 1); + fd = CMSG_DATA(cm); if ((unsigned) fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { return (EBADF); diff --git a/sys/sys/domain.h b/sys/sys/domain.h index 01a59f6..2ae9fba 100644 --- a/sys/sys/domain.h +++ b/sys/sys/domain.h @@ -52,7 +52,7 @@ struct domain { void (*dom_init) /* initialize domain data structures */ __P((void)); int (*dom_externalize) /* externalize access rights */ - __P((struct mbuf *)); + __P((struct mbuf *, struct mbuf **)); void (*dom_dispose) /* dispose of internalized rights */ __P((struct mbuf *)); struct protosw *dom_protosw, *dom_protoswNPROTOSW; diff --git a/sys/sys/un.h b/sys/sys/un.h index becf3ff..e4ce14c 100644 --- a/sys/sys/un.h +++ b/sys/sys/un.h @@ -59,7 +59,7 @@ int uipc_usrreq __P((struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control)); int unp_connect2 __P((struct socket *so, struct socket *so2)); void unp_dispose __P((struct mbuf *m)); -int unp_externalize __P((struct mbuf *rights)); +int unp_externalize __P((struct mbuf *mbuf, struct mbuf **controlp)); void unp_init __P((void)); extern struct pr_usrreqs uipc_usrreqs; #else /* !_KERNEL */ diff --git a/usr.sbin/mount_portalfs/activate.c b/usr.sbin/mount_portalfs/activate.c index 5646498..6143620 100644 --- a/usr.sbin/mount_portalfs/activate.c +++ b/usr.sbin/mount_portalfs/activate.c @@ -113,9 +113,9 @@ int error; int n; struct iovec iov; struct msghdr msg; - struct { + union { struct cmsghdr cmsg; - int fd; + char control[CMSG_SPACE(sizeof(int))]; } ctl; /* @@ -137,10 +137,10 @@ int error; * construct a suitable rights control message. */ if (fd >= 0) { - ctl.fd = fd; - ctl.cmsg.cmsg_len = sizeof(ctl); + ctl.cmsg.cmsg_len = CMSG_LEN(sizeof(int)); ctl.cmsg.cmsg_level = SOL_SOCKET; ctl.cmsg.cmsg_type = SCM_RIGHTS; + *((int *)CMSG_DATA(&ctl.cmsg)) = fd; msg.msg_control = (caddr_t) &ctl; msg.msg_controllen = ctl.cmsg.cmsg_len; } diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index 6b76231..908a9a6 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -1364,8 +1364,8 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s) return; } - fd = (int *)(cmsg + 1); - nfd = (cmsg->cmsg_len - sizeof *cmsg) / sizeof(int); + fd = (int *)CMSG_DATA(cmsg); + nfd = ((caddr_t)cmsg + cmsg->cmsg_len - (caddr_t)fd) / sizeof(int); if (nfd < 2) { log_Printf(LogERROR, "Recvmsg: %d descriptor%s received (too few) !\n", @@ -1457,7 +1457,7 @@ bundle_ReceiveDatalink(struct bundle *bundle, int s) void bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) { - char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int) * SEND_MAXFD]; + char cmsgbuf[CMSG_SPACE(sizeof(int) * SEND_MAXFD)]; const char *constlock; char *lock; struct cmsghdr *cmsg; @@ -1507,7 +1507,7 @@ bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) msg.msg_iovlen = 1; msg.msg_iov = iov; msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof *cmsg + sizeof(int) * nfd; + msg.msg_controllen = CMSG_SPACE(sizeof(int) * nfd); msg.msg_flags = 0; cmsg = (struct cmsghdr *)cmsgbuf; @@ -1516,7 +1516,7 @@ bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) cmsg->cmsg_type = SCM_RIGHTS; for (f = 0; f < nfd; f++) - *((int *)(cmsg + 1) + f) = fd[f]; + *((int *)CMSG_DATA(cmsg) + f) = fd[f]; for (f = 1, expect = 0; f < niov; f++) expect += iov[f].iov_len; |