Module Name: src Committed By: roy Date: Mon Mar 19 16:26:26 UTC 2018
Modified Files: src/lib/libc/sys: recv.2 src/sys/kern: uipc_socket2.c uipc_usrreq.c src/sys/net: raw_usrreq.c src/sys/netinet: udp_usrreq.c src/sys/netinet6: udp6_usrreq.c src/sys/netipsec: keysock.c src/sys/sys: socketvar.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.37 -r1.38 src/lib/libc/sys/recv.2 cvs rdiff -u -r1.127 -r1.128 src/sys/kern/uipc_socket2.c cvs rdiff -u -r1.183 -r1.184 src/sys/kern/uipc_usrreq.c cvs rdiff -u -r1.58 -r1.59 src/sys/net/raw_usrreq.c cvs rdiff -u -r1.245 -r1.246 src/sys/netinet/udp_usrreq.c cvs rdiff -u -r1.137 -r1.138 src/sys/netinet6/udp6_usrreq.c cvs rdiff -u -r1.62 -r1.63 src/sys/netipsec/keysock.c cvs rdiff -u -r1.150 -r1.151 src/sys/sys/socketvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/sys/recv.2 diff -u src/lib/libc/sys/recv.2:1.37 src/lib/libc/sys/recv.2:1.38 --- src/lib/libc/sys/recv.2:1.37 Sun Jun 11 17:34:54 2017 +++ src/lib/libc/sys/recv.2 Mon Mar 19 16:26:26 2018 @@ -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 @@ any data were available. .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 Index: src/sys/kern/uipc_socket2.c diff -u src/sys/kern/uipc_socket2.c:1.127 src/sys/kern/uipc_socket2.c:1.128 --- src/sys/kern/uipc_socket2.c:1.127 Sun Mar 18 15:32:48 2018 +++ src/sys/kern/uipc_socket2.c Mon Mar 19 16:26:26 2018 @@ -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 @@ socantrcvmore(struct socket *so) } /* + * 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 Index: src/sys/kern/uipc_usrreq.c diff -u src/sys/kern/uipc_usrreq.c:1.183 src/sys/kern/uipc_usrreq.c:1.184 --- src/sys/kern/uipc_usrreq.c:1.183 Sat Feb 17 20:19:36 2018 +++ src/sys/kern/uipc_usrreq.c Mon Mar 19 16:26:26 2018 @@ -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 @@ unp_output(struct mbuf *m, struct mbuf * #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); Index: src/sys/net/raw_usrreq.c diff -u src/sys/net/raw_usrreq.c:1.58 src/sys/net/raw_usrreq.c:1.59 --- src/sys/net/raw_usrreq.c:1.58 Mon Sep 25 01:57:54 2017 +++ src/sys/net/raw_usrreq.c Mon Mar 19 16:26:25 2018 @@ -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 @@ raw_input(struct mbuf *m0, ...) 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); } } Index: src/sys/netinet/udp_usrreq.c diff -u src/sys/netinet/udp_usrreq.c:1.245 src/sys/netinet/udp_usrreq.c:1.246 --- src/sys/netinet/udp_usrreq.c:1.245 Wed Feb 28 11:23:24 2018 +++ src/sys/netinet/udp_usrreq.c Mon Mar 19 16:26:25 2018 @@ -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 @@ udp4_sendup(struct mbuf *m, int off /* o m_freem(n); if (opts) m_freem(opts); - so->so_rcv.sb_overflowed++; UDP_STATINC(UDP_STAT_FULLSOCK); + soroverflow(so); } else sorwakeup(so); } Index: src/sys/netinet6/udp6_usrreq.c diff -u src/sys/netinet6/udp6_usrreq.c:1.137 src/sys/netinet6/udp6_usrreq.c:1.138 --- src/sys/netinet6/udp6_usrreq.c:1.137 Wed Feb 28 11:23:24 2018 +++ src/sys/netinet6/udp6_usrreq.c Mon Mar 19 16:26:25 2018 @@ -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 @@ udp6_sendup(struct mbuf *m, int off /* o m_freem(n); if (opts) m_freem(opts); - so->so_rcv.sb_overflowed++; UDP6_STATINC(UDP6_STAT_FULLSOCK); + soroverflow(so); } else sorwakeup(so); } Index: src/sys/netipsec/keysock.c diff -u src/sys/netipsec/keysock.c:1.62 src/sys/netipsec/keysock.c:1.63 --- src/sys/netipsec/keysock.c:1.62 Thu Sep 28 17:21:42 2017 +++ src/sys/netipsec/keysock.c Mon Mar 19 16:26:26 2018 @@ -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 @@ key_sendup0( __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; } Index: src/sys/sys/socketvar.h diff -u src/sys/sys/socketvar.h:1.150 src/sys/sys/socketvar.h:1.151 --- src/sys/sys/socketvar.h:1.150 Sun Mar 18 15:42:37 2018 +++ src/sys/sys/socketvar.h Mon Mar 19 16:26:26 2018 @@ -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 sofamily(const struct socket *); 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 *);