Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src socket: report receive buffer overflows



details:   https://anonhg.NetBSD.org/src/rev/d3fe50ea3a8f
branches:  trunk
changeset: 321513:d3fe50ea3a8f
user:      roy <roy%NetBSD.org@localhost>
date:      Mon Mar 19 16:26:25 2018 +0000

description:
socket: report receive buffer overflows

Add soroverflow() which increments the overflow counter, sets so_error
to ENOBUFS and wakes the receive socket up.
Replace all code that manually increments this counter with soroverflow().
Add soroverflow() to raw_input().

This allows userland to detect route(4) overflows so it can re-sync
with the current state.

diffstat:

 lib/libc/sys/recv.2        |   6 ++++--
 sys/kern/uipc_socket2.c    |  18 ++++++++++++++++--
 sys/kern/uipc_usrreq.c     |   6 +++---
 sys/net/raw_usrreq.c       |  31 ++++++++++++++++++-------------
 sys/netinet/udp_usrreq.c   |   6 +++---
 sys/netinet6/udp6_usrreq.c |   6 +++---
 sys/netipsec/keysock.c     |  11 ++++++-----
 sys/sys/socketvar.h        |   3 ++-
 8 files changed, 55 insertions(+), 32 deletions(-)

diffs (259 lines):

diff -r 51db75fd3e35 -r d3fe50ea3a8f lib/libc/sys/recv.2
--- a/lib/libc/sys/recv.2       Mon Mar 19 16:19:17 2018 +0000
+++ b/lib/libc/sys/recv.2       Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: recv.2,v 1.37 2017/06/11 17:34:54 abhinav Exp $
+.\"    $NetBSD: recv.2,v 1.38 2018/03/19 16:26:26 roy Exp $
 .\"
 .\" Copyright (c) 1983, 1990, 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"     @(#)recv.2     8.3 (Berkeley) 2/21/94
 .\"
-.Dd June 22, 2012
+.Dd March 19, 2018
 .Dt RECV 2
 .Os
 .Sh NAME
@@ -319,6 +319,8 @@
 .It Bq Er EINVAL
 The total length of the I/O is more than can be expressed by the ssize_t
 return value.
+.It Bq Er ENOBUFS
+A message was not delivered because it would have overflowed the buffer.
 .It Bq Er ENOTCONN
 The socket is associated with a connection-oriented protocol
 and has not been connected (see
diff -r 51db75fd3e35 -r d3fe50ea3a8f sys/kern/uipc_socket2.c
--- a/sys/kern/uipc_socket2.c   Mon Mar 19 16:19:17 2018 +0000
+++ b/sys/kern/uipc_socket2.c   Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_socket2.c,v 1.127 2018/03/18 15:32:48 christos Exp $      */
+/*     $NetBSD: uipc_socket2.c,v 1.128 2018/03/19 16:26:26 roy Exp $   */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.127 2018/03/18 15:32:48 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.128 2018/03/19 16:26:26 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_mbuftrace.h"
@@ -495,6 +495,20 @@
 }
 
 /*
+ * soroverflow(): indicates that data was attempted to be sent
+ * but the receiving buffer overflowed.
+ */
+void
+soroverflow(struct socket *so)
+{
+       KASSERT(solocked(so));
+
+       so->so_rcv.sb_overflowed++;
+       so->so_error = ENOBUFS;
+       sorwakeup(so);
+}
+
+/*
  * Wait for data to arrive at/drain from a socket buffer.
  */
 int
diff -r 51db75fd3e35 -r d3fe50ea3a8f sys/kern/uipc_usrreq.c
--- a/sys/kern/uipc_usrreq.c    Mon Mar 19 16:19:17 2018 +0000
+++ b/sys/kern/uipc_usrreq.c    Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_usrreq.c,v 1.183 2018/02/17 20:19:36 christos Exp $       */
+/*     $NetBSD: uipc_usrreq.c,v 1.184 2018/03/19 16:26:26 roy Exp $    */
 
 /*-
  * Copyright (c) 1998, 2000, 2004, 2008, 2009 The NetBSD Foundation, Inc.
@@ -96,7 +96,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.183 2018/02/17 20:19:36 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_usrreq.c,v 1.184 2018/03/19 16:26:26 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -342,10 +342,10 @@
 #endif
        if (sbappendaddr(&so2->so_rcv, (const struct sockaddr *)sun, m,
            control) == 0) {
-               so2->so_rcv.sb_overflowed++;
                unp_dispose(control);
                m_freem(control);
                m_freem(m);
+               soroverflow(so2);
                return (ENOBUFS);
        } else {
                sorwakeup(so2);
diff -r 51db75fd3e35 -r d3fe50ea3a8f sys/net/raw_usrreq.c
--- a/sys/net/raw_usrreq.c      Mon Mar 19 16:19:17 2018 +0000
+++ b/sys/net/raw_usrreq.c      Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: raw_usrreq.c,v 1.58 2017/09/25 01:57:54 ozaki-r Exp $  */
+/*     $NetBSD: raw_usrreq.c,v 1.59 2018/03/19 16:26:25 roy Exp $      */
 
 /*
  * Copyright (c) 1980, 1986, 1993
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.58 2017/09/25 01:57:54 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: raw_usrreq.c,v 1.59 2018/03/19 16:26:25 roy Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
@@ -106,21 +106,26 @@
                        continue;
                if (last != NULL) {
                        struct mbuf *n;
-                       if ((n = m_copy(m, 0, M_COPYALL)) == NULL)
-                               ;
-                       else if (sbappendaddr(&last->so_rcv, src, n, NULL) == 0)
-                               /* should notify about lost packet */
-                               m_freem(n);
-                       else {
+
+                       if ((n = m_copy(m, 0, M_COPYALL)) == NULL ||
+                           sbappendaddr(&last->so_rcv, src, n, NULL) == 0)
+                       {
+                               if (n != NULL)
+                                       m_freem(n);
+                               soroverflow(last);
+                       } else
                                sorwakeup(last);
-                       }
                }
                last = rp->rcb_socket;
        }
-       if (last == NULL || sbappendaddr(&last->so_rcv, src, m, NULL) == 0)
-               m_freem(m);
-       else {
-               sorwakeup(last);
+       if (last != NULL) {
+               if (sbappendaddr(&last->so_rcv, src, m, NULL) == 0) {
+                       m_free(m);
+                       soroverflow(last);
+               } else
+                       sorwakeup(last);
+       } else {
+               m_free(m);
        }
 }
 
diff -r 51db75fd3e35 -r d3fe50ea3a8f sys/netinet/udp_usrreq.c
--- a/sys/netinet/udp_usrreq.c  Mon Mar 19 16:19:17 2018 +0000
+++ b/sys/netinet/udp_usrreq.c  Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: udp_usrreq.c,v 1.245 2018/02/28 11:23:24 maxv Exp $    */
+/*     $NetBSD: udp_usrreq.c,v 1.246 2018/03/19 16:26:25 roy Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.245 2018/02/28 11:23:24 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.246 2018/03/19 16:26:25 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -498,8 +498,8 @@
                        m_freem(n);
                        if (opts)
                                m_freem(opts);
-                       so->so_rcv.sb_overflowed++;
                        UDP_STATINC(UDP_STAT_FULLSOCK);
+                       soroverflow(so);
                } else
                        sorwakeup(so);
        }
diff -r 51db75fd3e35 -r d3fe50ea3a8f sys/netinet6/udp6_usrreq.c
--- a/sys/netinet6/udp6_usrreq.c        Mon Mar 19 16:19:17 2018 +0000
+++ b/sys/netinet6/udp6_usrreq.c        Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: udp6_usrreq.c,v 1.137 2018/02/28 11:23:24 maxv Exp $ */
+/* $NetBSD: udp6_usrreq.c,v 1.138 2018/03/19 16:26:25 roy Exp $ */
 /* $KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $ */
 /* $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $ */
 
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.137 2018/02/28 11:23:24 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.138 2018/03/19 16:26:25 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -372,8 +372,8 @@
                        m_freem(n);
                        if (opts)
                                m_freem(opts);
-                       so->so_rcv.sb_overflowed++;
                        UDP6_STATINC(UDP6_STAT_FULLSOCK);
+                       soroverflow(so);
                } else
                        sorwakeup(so);
        }
diff -r 51db75fd3e35 -r d3fe50ea3a8f sys/netipsec/keysock.c
--- a/sys/netipsec/keysock.c    Mon Mar 19 16:19:17 2018 +0000
+++ b/sys/netipsec/keysock.c    Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: keysock.c,v 1.62 2017/09/28 17:21:42 christos Exp $    */
+/*     $NetBSD: keysock.c,v 1.63 2018/03/19 16:26:26 roy Exp $ */
 /*     $FreeBSD: src/sys/netipsec/keysock.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $    */
 /*     $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $        */
 
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.62 2017/09/28 17:21:42 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.63 2018/03/19 16:26:26 roy Exp $");
 
 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
 
@@ -207,11 +207,12 @@
                    __func__);
                PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
                m_freem(m);
+               soroverflow(rp->rcb_socket);
                error = ENOBUFS;
-               rp->rcb_socket->so_rcv.sb_overflowed++;
-       } else
+       } else {
+               sorwakeup(rp->rcb_socket);
                error = 0;
-       sorwakeup(rp->rcb_socket);
+       }
        return error;
 }
 
diff -r 51db75fd3e35 -r d3fe50ea3a8f sys/sys/socketvar.h
--- a/sys/sys/socketvar.h       Mon Mar 19 16:19:17 2018 +0000
+++ b/sys/sys/socketvar.h       Mon Mar 19 16:26:25 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: socketvar.h,v 1.150 2018/03/18 15:42:37 christos Exp $ */
+/*     $NetBSD: socketvar.h,v 1.151 2018/03/19 16:26:26 roy Exp $      */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -301,6 +301,7 @@
 int    sobind(struct socket *, struct sockaddr *, struct lwp *);
 void   socantrcvmore(struct socket *);
 void   socantsendmore(struct socket *);
+void   soroverflow(struct socket *);
 int    soclose(struct socket *);
 int    soconnect(struct socket *, struct sockaddr *, struct lwp *);
 int    soconnect2(struct socket *, struct socket *);



Home | Main Index | Thread Index | Old Index