1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-17 15:27:36 +00:00

In r248885 I have reduced size of fake uio resid that ng_ksocket(4) passes

to the soreceive(). This exposed a bug. When reading from a raw socket,
when our fake limit is depleted, we receive a truncated mbuf chain, with
m->m_pkthdr.len > m_length(m). The first problem is that MSG_TRUNC was not
handled. The second one is that we didn't reinit uio_resid in our endless
loop (neither flags), and if socket buffer contained several records, then
we quickly deplete our fake limit. The third bug, actually introduced in
r248885, is that MJUMPAGESIZE isn't enough to handle maximum packet that
ng_ksocket(4) can theoretically receive.

Changes:
- Reinit uio_resid and flags before every call to soreceive().
- Set maximum acceptable size of packet to IP_MAXPACKET. As for now the
  module doesn't support INET6.
- Properly handle MSG_TRUNC return from soreceive().

PR:			184601
Submitted & tested by:	Viktor Velichkin <avisom yandex.ru>
Sponsored by:		Nginx, Inc.
This commit is contained in:
Gleb Smirnoff 2013-12-21 14:41:32 +00:00
parent 41fb066511
commit 9165bf6297
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=259681

View File

@ -66,6 +66,7 @@
#include <netgraph/ng_ksocket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netatalk/at.h>
#ifdef NG_SEPARATE_MALLOC
@ -1043,8 +1044,7 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2)
struct socket *so = arg1;
const priv_p priv = NG_NODE_PRIVATE(node);
struct ng_mesg *response;
struct uio auio;
int flags, error;
int error;
KASSERT(so == priv->so, ("%s: wrong socket", __func__));
@ -1093,20 +1093,27 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2)
if (priv->hook == NULL)
return;
/* Read and forward available mbuf's */
auio.uio_td = NULL;
auio.uio_resid = MJUMPAGESIZE; /* XXXGL: sane limit? */
flags = MSG_DONTWAIT;
/* Read and forward available mbufs. */
while (1) {
struct sockaddr *sa = NULL;
struct uio uio;
struct sockaddr *sa;
struct mbuf *m;
int flags;
/* Try to get next packet from socket */
/* Try to get next packet from socket. */
uio.uio_td = NULL;
uio.uio_resid = IP_MAXPACKET;
flags = MSG_DONTWAIT;
sa = NULL;
if ((error = soreceive(so, (so->so_state & SS_ISCONNECTED) ?
NULL : &sa, &auio, &m, NULL, &flags)) != 0)
NULL : &sa, &uio, &m, NULL, &flags)) != 0)
break;
/* See if we got anything */
/* See if we got anything. */
if (flags & MSG_TRUNC) {
m_freem(m);
m = NULL;
}
if (m == NULL) {
if (sa != NULL)
free(sa, M_SONAME);