From owner-svn-src-head@FreeBSD.ORG Sat Dec 21 14:41:33 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 13F16E65; Sat, 21 Dec 2013 14:41:33 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id D894619D5; Sat, 21 Dec 2013 14:41:32 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rBLEfWWG072414; Sat, 21 Dec 2013 14:41:32 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id rBLEfWko072413; Sat, 21 Dec 2013 14:41:32 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201312211441.rBLEfWko072413@svn.freebsd.org> From: Gleb Smirnoff Date: Sat, 21 Dec 2013 14:41:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r259681 - head/sys/netgraph X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 21 Dec 2013 14:41:33 -0000 Author: glebius Date: Sat Dec 21 14:41:32 2013 New Revision: 259681 URL: http://svnweb.freebsd.org/changeset/base/259681 Log: 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 Sponsored by: Nginx, Inc. Modified: head/sys/netgraph/ng_ksocket.c Modified: head/sys/netgraph/ng_ksocket.c ============================================================================== --- head/sys/netgraph/ng_ksocket.c Sat Dec 21 13:58:55 2013 (r259680) +++ head/sys/netgraph/ng_ksocket.c Sat Dec 21 14:41:32 2013 (r259681) @@ -66,6 +66,7 @@ #include #include +#include #include #ifdef NG_SEPARATE_MALLOC @@ -1043,8 +1044,7 @@ ng_ksocket_incoming2(node_p node, hook_p 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 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);