Page MenuHomeFreeBSD

D35302.id106549.diff
No OneTemporary

D35302.id106549.diff

Index: sys/kern/uipc_usrreq.c
===================================================================
--- sys/kern/uipc_usrreq.c
+++ sys/kern/uipc_usrreq.c
@@ -302,11 +302,13 @@
static void unp_scan(struct mbuf *, void (*)(struct filedescent **, int));
static void unp_discard(struct file *);
static void unp_freerights(struct filedescent **, int);
-static int unp_internalize(struct mbuf **, struct thread *);
+static int unp_internalize(struct mbuf **, struct thread *,
+ struct mbuf **, u_int *, u_int *);
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 *, int);
+static struct mbuf *unp_addsockcred(struct thread *, struct mbuf *,
+ int, struct mbuf **, u_int *, u_int *);
static void unp_process_defers(void * __unused, int);
static void
@@ -1014,7 +1016,8 @@
error = EOPNOTSUPP;
goto release;
}
- if (control != NULL && (error = unp_internalize(&control, td)))
+ if (control != NULL &&
+ (error = unp_internalize(&control, td, NULL, NULL, NULL)))
goto release;
unp2 = NULL;
@@ -1051,7 +1054,8 @@
* SOCK_SEQPACKET (LOCAL_CREDS => WANTCRED_ONESHOT), or
* forever (LOCAL_CREDS_PERSISTENT => WANTCRED_ALWAYS).
*/
- control = unp_addsockcred(td, control, unp2->unp_flags);
+ control = unp_addsockcred(td, control, unp2->unp_flags, NULL,
+ NULL, NULL);
unp2->unp_flags &= ~UNP_WANTCRED_ONESHOT;
}
@@ -1140,8 +1144,8 @@
const struct sockaddr *from;
struct socket *so2;
struct sockbuf *sb;
- struct mbuf *f;
- u_int space;
+ struct mbuf *f, *clast;
+ u_int space, mbcnt, dspace __diagused, dmbcnt __diagused;
int error;
MPASS((uio != NULL && m == NULL) || (m != NULL && uio == NULL));
@@ -1163,8 +1167,11 @@
error = EFAULT;
goto out;
}
- f = m_get(M_WAITOK, MT_SONAME);
- if (c != NULL && (error = unp_internalize(&c, td)))
+ f = m_gethdr(M_WAITOK, MT_SONAME);
+ space = m->m_pkthdr.len;
+ mbcnt = MSIZE + m->m_pkthdr.memlen;
+ if (c != NULL &&
+ (error = unp_internalize(&c, td, &clast, &space, &mbcnt)))
goto out;
} else {
/* pru_sosend() with mbuf usually is a kernel thread. */
@@ -1177,7 +1184,7 @@
error = EMSGSIZE;
goto out;
}
- if ((f = m_get(M_NOWAIT, MT_SONAME)) == NULL) {
+ if ((f = m_gethdr(M_NOWAIT, MT_SONAME)) == NULL) {
error = ENOBUFS;
goto out;
}
@@ -1189,6 +1196,14 @@
m->m_pkthdr.csum_flags = 0;
m->m_pkthdr.fibnum = 0;
m->m_pkthdr.rsstype = 0;
+
+ space = m->m_pkthdr.len;
+ mbcnt = MSIZE;
+ for (struct mbuf *mb = m; mb != NULL; mb = mb->m_next) {
+ mbcnt += MSIZE;
+ if (mb->m_flags & M_EXT)
+ mbcnt += mb->m_ext.ext_size;
+ }
}
unp = sotounpcb(so);
@@ -1240,7 +1255,8 @@
}
if (unp2->unp_flags & UNP_WANTCRED_MASK)
- c = unp_addsockcred(td, c, unp2->unp_flags);
+ c = unp_addsockcred(td, c, unp2->unp_flags, &clast, &space,
+ &mbcnt);
if (unp->unp_addr != NULL)
from = (struct sockaddr *)unp->unp_addr;
else
@@ -1248,33 +1264,48 @@
f->m_len = from->sa_len;
MPASS(from->sa_len <= MLEN);
bcopy(from, mtod(f, void *), from->sa_len);
- space = f->m_len + m->m_pkthdr.len;
+ space += f->m_len;
- /* Concatenate: from -> control -> data. */
+ /*
+ * Concatenate mbufs: from -> control -> data.
+ * Save overall space and mbcnt in "from" mbuf.
+ */
if (c != NULL) {
- struct mbuf *clast;
+#ifdef INVARIANTS
+ struct mbuf *mc;
- space += m_length(c, &clast);
+ for (mc = c; mc->m_next != NULL; mc = mc->m_next);
+ MPASS(mc == clast);
+#endif
f->m_next = c;
clast->m_next = m;
c = NULL;
} else
f->m_next = m;
m = NULL;
+ f->m_pkthdr.len = space;
+ f->m_pkthdr.memlen = mbcnt;
+#ifdef INVARIANTS
+ dspace = dmbcnt = 0;
+ for (struct mbuf *mb = f; mb != NULL; mb = mb->m_next) {
+ dspace += mb->m_len;
+ dmbcnt += MSIZE;
+ if (mb->m_flags & M_EXT)
+ dmbcnt += mb->m_ext.ext_size;
+ }
+ MPASS(dspace == space);
+ MPASS(dmbcnt == mbcnt);
+#endif
so2 = unp2->unp_socket;
sb = &so2->so_rcv;
SOCK_RECVBUF_LOCK(so2);
if (space <= sbspace(sb)) {
STAILQ_INSERT_TAIL(&sb->uxdg_mb, f, m_stailqpkt);
- /* XXX: would be nice if m_uiotombuf() returns count. */
- for (; f != NULL ; f = f->m_next) {
- sb->sb_mbcnt += MSIZE;
- if (f->m_flags & M_EXT)
- sb->sb_mbcnt += f->m_ext.ext_size;
- }
sb->sb_ccc += space;
+ sb->sb_mbcnt += mbcnt;
sorwakeup_locked(so2);
+ f = NULL;
} else {
soroverflow_locked(so2);
error = (so->so_state & SS_NBIO) ? EAGAIN : ENOBUFS;
@@ -1363,7 +1394,7 @@
uipc_soreceive_dgram(struct socket *so, struct sockaddr **psa, struct uio *uio,
struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
{
- struct mbuf *m, *m2;
+ struct mbuf *m;
int flags, error;
ssize_t len;
bool nonblock;
@@ -1416,7 +1447,9 @@
return (error);
}
}
- SOCK_RECVBUF_LOCK_ASSERT(so);
+
+ M_ASSERTPKTHDR(m);
+ KASSERT(m->m_type == MT_SONAME, ("m->m_type == %d", m->m_type));
if (uio->uio_td)
uio->uio_td->td_ru.ru_msgrcv++;
@@ -1425,15 +1458,10 @@
return (uipc_peek_dgram(so, psa, uio, controlp, flagsp));
STAILQ_REMOVE_HEAD(&so->so_rcv.uxdg_mb, m_stailqpkt);
- for (m2 = m; m2 != NULL; m2 = m2->m_next) {
- so->so_rcv.sb_ccc -= m2->m_len;
- so->so_rcv.sb_mbcnt -= MSIZE;
- if (m2->m_flags & M_EXT)
- so->so_rcv.sb_mbcnt -= m2->m_ext.ext_size;
- }
+ so->so_rcv.sb_ccc -= m->m_pkthdr.len;
+ so->so_rcv.sb_mbcnt -= m->m_pkthdr.memlen;
SOCK_RECVBUF_UNLOCK(so);
- KASSERT(m->m_type == MT_SONAME, ("m->m_type == %d", m->m_type));
if (psa != NULL)
*psa = sodupsockaddr(mtod(m, struct sockaddr *), M_WAITOK);
m = m_free(m);
@@ -2504,7 +2532,8 @@
}
static int
-unp_internalize(struct mbuf **controlp, struct thread *td)
+unp_internalize(struct mbuf **controlp, struct thread *td,
+ struct mbuf **clast, u_int *space, u_int *mbcnt)
{
struct mbuf *control, **initial_controlp;
struct proc *p;
@@ -2521,6 +2550,7 @@
int i, j, error, *fdp, oldfds;
u_int newlen;
+ MPASS((*controlp)->m_next == NULL); /* COMPAT_OLDSOCK may violate */
UNP_LINK_UNLOCK_ASSERT();
p = td->td_proc;
@@ -2667,6 +2697,13 @@
goto out;
}
+ if (space != NULL) {
+ *space += (*controlp)->m_len;
+ *mbcnt += MSIZE;
+ if ((*controlp)->m_flags & M_EXT)
+ *mbcnt += (*controlp)->m_ext.ext_size;
+ *clast = *controlp;
+ }
controlp = &(*controlp)->m_next;
}
if (clen > 0)
@@ -2680,7 +2717,8 @@
}
static struct mbuf *
-unp_addsockcred(struct thread *td, struct mbuf *control, int mode)
+unp_addsockcred(struct thread *td, struct mbuf *control, int mode,
+ struct mbuf **clast, u_int *space, u_int *mbcnt)
{
struct mbuf *m, *n, *n_prev;
const struct cmsghdr *cm;
@@ -2699,6 +2737,7 @@
m = sbcreatecontrol(NULL, ctrlsz, cmsgtype, SOL_SOCKET, M_NOWAIT);
if (m == NULL)
return (control);
+ MPASS((m->m_flags & M_EXT) == 0 && m->m_next == NULL);
if (mode & UNP_WANTCRED_ALWAYS) {
struct sockcred2 *sc;
@@ -2740,6 +2779,25 @@
control = n->m_next;
else
n_prev->m_next = n->m_next;
+ if (space != NULL) {
+ MPASS(*space >= n->m_len);
+ *space -= n->m_len;
+ MPASS(*mbcnt >= MSIZE);
+ *mbcnt -= MSIZE;
+ if (n->m_flags & M_EXT) {
+ MPASS(*mbcnt >=
+ n->m_ext.ext_size);
+ *mbcnt -= n->m_ext.ext_size;
+ }
+ MPASS(clast);
+ if (*clast == n) {
+ MPASS(n->m_next == NULL);
+ if (n_prev == NULL)
+ *clast = m;
+ else
+ *clast = n_prev;
+ }
+ }
n = m_free(n);
} else {
n_prev = n;
@@ -2749,6 +2807,10 @@
/* Prepend it to the head. */
m->m_next = control;
+ if (space != NULL) {
+ *space += m->m_len;
+ *mbcnt += MSIZE;
+ }
return (m);
}

File Metadata

Mime Type
text/plain
Expires
Mon, Jan 20, 4:22 PM (18 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15979647
Default Alt Text
D35302.id106549.diff (7 KB)

Event Timeline