Page MenuHomeFreeBSD

D26652.id77847.diff
No OneTemporary

D26652.id77847.diff

Index: lib/libc/sys/getsockopt.2
===================================================================
--- lib/libc/sys/getsockopt.2
+++ lib/libc/sys/getsockopt.2
@@ -28,7 +28,7 @@
.\" @(#)getsockopt.2 8.4 (Berkeley) 5/2/95
.\" $FreeBSD$
.\"
-.Dd June 03, 2020
+.Dd October 04, 2020
.Dt GETSOCKOPT 2
.Os
.Sh NAME
@@ -177,6 +177,7 @@
.It Dv SO_PROTOCOL Ta "get the protocol number for the socket (get only)"
.It Dv SO_PROTOTYPE Ta "SunOS alias for the Linux SO_PROTOCOL (get only)"
.It Dv SO_ERROR Ta "get and clear error on the socket (get only)"
+.It Dv SO_RERROR Ta "enables receive error reporting"
.It Dv SO_SETFIB Ta "set the associated FIB (routing table) for the socket (set only)"
.El
.Pp
@@ -513,6 +514,13 @@
the error status.
It may be used to check for asynchronous errors on connected
datagram sockets or for other asynchronous errors.
+.Dv SO_RERROR
+indicates that receive buffer overflows should be handled as errors.
+Historically receive buffer overflows have been ignored and programs
+could not tell if they missed messages or messages had been truncated
+because of overflows.
+Since programs historically do not expect to get receive overflow errors,
+this behavior is not the default.
.Pp
.Dv SO_LABEL
returns the MAC label of the socket.
Index: sbin/route/route.c
===================================================================
--- sbin/route/route.c
+++ sbin/route/route.c
@@ -1485,9 +1485,20 @@
interfaces();
exit(0);
}
+
+#ifdef SO_RERROR
+ n = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_RERROR, &n, sizeof(n)) == -1)
+ warn("SO_RERROR");
+#endif
+
for (;;) {
time_t now;
- n = read(s, msg, 2048);
+ n = read(s, msg, sizeof(msg));
+ if (n == -1) {
+ warn("read");
+ continue;
+ }
now = time(NULL);
(void)printf("\ngot message of size %d on %s", n, ctime(&now));
print_rtmsg((struct rt_msghdr *)(void *)msg, n);
Index: sys/kern/uipc_sockbuf.c
===================================================================
--- sys/kern/uipc_sockbuf.c
+++ sys/kern/uipc_sockbuf.c
@@ -436,6 +436,30 @@
mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED);
}
+void
+soroverflow_locked(struct socket *so)
+{
+
+ SOCKBUF_LOCK_ASSERT(&so->so_rcv);
+
+ if (so->so_options & SO_RERROR) {
+ so->so_rerror = ENOBUFS;
+ sorwakeup_locked(so);
+ } else
+ SOCKBUF_UNLOCK(&so->so_rcv);
+
+ mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED);
+}
+
+void
+soroverflow(struct socket *so)
+{
+
+ SOCKBUF_LOCK(&so->so_rcv);
+ soroverflow_locked(so);
+ mtx_assert(SOCKBUF_MTX(&so->so_rcv), MA_NOTOWNED);
+}
+
/*
* Wait for data to arrive at/drain from a socket buffer.
*/
Index: sys/kern/uipc_socket.c
===================================================================
--- sys/kern/uipc_socket.c
+++ sys/kern/uipc_socket.c
@@ -1954,12 +1954,19 @@
KASSERT(m != NULL || !sbavail(&so->so_rcv),
("receive: m == %p sbavail == %u",
m, sbavail(&so->so_rcv)));
- if (so->so_error) {
+ if (so->so_error || so->so_rerror) {
if (m != NULL)
goto dontblock;
- error = so->so_error;
- if ((flags & MSG_PEEK) == 0)
- so->so_error = 0;
+ if (so->so_error)
+ error = so->so_error;
+ else
+ error = so->so_rerror;
+ if ((flags & MSG_PEEK) == 0) {
+ if (so->so_error)
+ so->so_error = 0;
+ else
+ so->so_rerror = 0;
+ }
SOCKBUF_UNLOCK(&so->so_rcv);
goto release;
}
@@ -2303,7 +2310,7 @@
while (flags & MSG_WAITALL && m == NULL && uio->uio_resid > 0 &&
!sosendallatonce(so) && nextrecord == NULL) {
SOCKBUF_LOCK_ASSERT(&so->so_rcv);
- if (so->so_error ||
+ if (so->so_error || so->so_rerror ||
so->so_rcv.sb_state & SBS_CANTRCVMORE)
break;
/*
@@ -3044,6 +3051,7 @@
case SO_NOSIGPIPE:
case SO_NO_DDP:
case SO_NO_OFFLOAD:
+ case SO_RERROR:
error = sooptcopyin(sopt, &optval, sizeof optval,
sizeof optval);
if (error)
@@ -3265,6 +3273,7 @@
case SO_NOSIGPIPE:
case SO_NO_DDP:
case SO_NO_OFFLOAD:
+ case SO_RERROR:
optval = so->so_options & sopt->sopt_name;
integer:
error = sooptcopyout(sopt, &optval, sizeof optval);
@@ -3284,8 +3293,13 @@
case SO_ERROR:
SOCK_LOCK(so);
- optval = so->so_error;
- so->so_error = 0;
+ if (so->so_error) {
+ optval = so->so_error;
+ so->so_error = 0;
+ } else {
+ optval = so->so_rerror;
+ so->so_rerror = 0;
+ }
SOCK_UNLOCK(so);
goto integer;
@@ -3834,7 +3848,7 @@
kn->kn_flags |= EV_EOF;
kn->kn_fflags = so->so_error;
return (1);
- } else if (so->so_error) /* temporary udp error */
+ } else if (so->so_error || so->so_rerror)
return (1);
if (kn->kn_sfflags & NOTE_LOWAT) {
Index: sys/kern/uipc_usrreq.c
===================================================================
--- sys/kern/uipc_usrreq.c
+++ sys/kern/uipc_usrreq.c
@@ -1054,7 +1054,7 @@
m = NULL;
control = NULL;
} else {
- SOCKBUF_UNLOCK(&so2->so_rcv);
+ soroverflow_locked(so2);
error = ENOBUFS;
}
if (nam != NULL)
Index: sys/net/raw_usrreq.c
===================================================================
--- sys/net/raw_usrreq.c
+++ sys/net/raw_usrreq.c
@@ -100,10 +100,10 @@
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
if (n) {
if (sbappendaddr(&last->so_rcv, src,
- n, (struct mbuf *)0) == 0)
- /* should notify about lost packet */
+ n, (struct mbuf *)0) == 0) {
+ soroverflow(last);
m_freem(n);
- else
+ } else
sorwakeup(last);
}
}
@@ -111,9 +111,10 @@
}
if (last) {
if (sbappendaddr(&last->so_rcv, src,
- m, (struct mbuf *)0) == 0)
+ m, (struct mbuf *)0) == 0) {
+ soroverflow(last);
m_freem(m);
- else
+ } else
sorwakeup(last);
} else
m_freem(m);
Index: sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
===================================================================
--- sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
+++ sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c
@@ -539,6 +539,7 @@
NG_FREE_M(m);
NG_FREE_M(ctl);
+ soroverflow(pcb->so);
}
}
next:
Index: sys/netgraph/ng_socket.c
===================================================================
--- sys/netgraph/ng_socket.c
+++ sys/netgraph/ng_socket.c
@@ -982,7 +982,7 @@
/* Send it up to the socket. */
if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&addr, m,
NULL) == 0) {
- SOCKBUF_UNLOCK(&so->so_rcv);
+ soroverflow_locked(so);
TRAP_ERROR;
m_freem(m);
return (ENOBUFS);
Index: sys/netinet/ip_divert.c
===================================================================
--- sys/netinet/ip_divert.c
+++ sys/netinet/ip_divert.c
@@ -285,7 +285,7 @@
if (sbappendaddr_locked(&sa->so_rcv,
(struct sockaddr *)&divsrc, m,
(struct mbuf *)0) == 0) {
- SOCKBUF_UNLOCK(&sa->so_rcv);
+ soroverflow_locked(sa);
sa = NULL; /* force mbuf reclaim below */
} else
sorwakeup_locked(sa);
Index: sys/netinet/ip_mroute.c
===================================================================
--- sys/netinet/ip_mroute.c
+++ sys/netinet/ip_mroute.c
@@ -1206,7 +1206,7 @@
sorwakeup_locked(s);
return 0;
}
- SOCKBUF_UNLOCK(&s->so_rcv);
+ soroverflow_locked(s);
}
m_freem(mm);
return -1;
Index: sys/netinet/raw_ip.c
===================================================================
--- sys/netinet/raw_ip.c
+++ sys/netinet/raw_ip.c
@@ -260,11 +260,10 @@
SOCKBUF_LOCK(&so->so_rcv);
if (sbappendaddr_locked(&so->so_rcv,
(struct sockaddr *)ripsrc, n, opts) == 0) {
- /* should notify about lost packet */
+ soroverflow_locked(so);
m_freem(n);
if (opts)
m_freem(opts);
- SOCKBUF_UNLOCK(&so->so_rcv);
} else
sorwakeup_locked(so);
} else
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -377,7 +377,7 @@
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_rcv);
if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) {
- SOCKBUF_UNLOCK(&so->so_rcv);
+ soroverflow(so);
m_freem(n);
if (opts)
m_freem(opts);
Index: sys/netinet6/icmp6.c
===================================================================
--- sys/netinet6/icmp6.c
+++ sys/netinet6/icmp6.c
@@ -1977,13 +1977,11 @@
&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, n, opts)
== 0) {
- /* should notify about lost packet */
+ soroverflow_locked(last->inp_socket);
m_freem(n);
if (opts) {
m_freem(opts);
}
- SOCKBUF_UNLOCK(
- &last->inp_socket->so_rcv);
} else
sorwakeup_locked(last->inp_socket);
opts = NULL;
@@ -2023,7 +2021,7 @@
m_freem(m);
if (opts)
m_freem(opts);
- SOCKBUF_UNLOCK(&last->inp_socket->so_rcv);
+ soroverflow_locked(last->inp_socket);
} else
sorwakeup_locked(last->inp_socket);
INP_RUNLOCK(last);
Index: sys/netinet6/ip6_input.c
===================================================================
--- sys/netinet6/ip6_input.c
+++ sys/netinet6/ip6_input.c
@@ -1576,6 +1576,7 @@
so = inp->inp_socket;
if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
== 0) {
+ soroverflow(so);
m_freem(m_mtu);
/* XXX: should count statistics */
} else
Index: sys/netinet6/ip6_mroute.c
===================================================================
--- sys/netinet6/ip6_mroute.c
+++ sys/netinet6/ip6_mroute.c
@@ -1038,7 +1038,8 @@
mm, (struct mbuf *)0) != 0) {
sorwakeup(s);
return (0);
- }
+ } else
+ soroverflow(s);
}
m_freem(mm);
return (-1);
Index: sys/netinet6/raw_ip6.c
===================================================================
--- sys/netinet6/raw_ip6.c
+++ sys/netinet6/raw_ip6.c
@@ -212,6 +212,7 @@
if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa,
n, opts) == 0) {
+ soroverflow(last->inp_socket);
m_freem(n);
if (opts)
m_freem(opts);
@@ -323,6 +324,7 @@
m_adj(m, *offp);
if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, m, opts) == 0) {
+ soroverflow(last->inp_socket);
m_freem(m);
if (opts)
m_freem(opts);
Index: sys/netinet6/send.c
===================================================================
--- sys/netinet6/send.c
+++ sys/netinet6/send.c
@@ -291,7 +291,7 @@
SOCKBUF_LOCK(&V_send_so->so_rcv);
if (sbappendaddr_locked(&V_send_so->so_rcv,
(struct sockaddr *)&sendsrc, m, NULL) == 0) {
- SOCKBUF_UNLOCK(&V_send_so->so_rcv);
+ soroverflow_locked(V_send_so);
/* XXX stats. */
m_freem(m);
} else {
Index: sys/netinet6/udp6_usrreq.c
===================================================================
--- sys/netinet6/udp6_usrreq.c
+++ sys/netinet6/udp6_usrreq.c
@@ -195,7 +195,7 @@
SOCKBUF_LOCK(&so->so_rcv);
if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&fromsa[0], n,
opts) == 0) {
- SOCKBUF_UNLOCK(&so->so_rcv);
+ soroverflow_locked(so);
m_freem(n);
if (opts)
m_freem(opts);
Index: sys/netipsec/keysock.c
===================================================================
--- sys/netipsec/keysock.c
+++ sys/netipsec/keysock.c
@@ -141,7 +141,6 @@
static int
key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc)
{
- int error;
if (promisc) {
struct sadb_msg *pmsg;
@@ -165,11 +164,12 @@
m, NULL)) {
PFKEYSTAT_INC(in_nomem);
m_freem(m);
- error = ENOBUFS;
- } else
- error = 0;
+ soroverflow(rp->rcb_socket);
+ return ENOBUFS;
+ }
+
sorwakeup(rp->rcb_socket);
- return error;
+ return 0;
}
/* so can be NULL if target != KEY_SENDUP_ONE */
Index: sys/sys/socket.h
===================================================================
--- sys/sys/socket.h
+++ sys/sys/socket.h
@@ -172,6 +172,7 @@
#define SO_TS_CLOCK 0x1017 /* clock type used for SO_TIMESTAMP */
#define SO_MAX_PACING_RATE 0x1018 /* socket's max TX pacing rate (Linux name) */
#define SO_DOMAIN 0x1019 /* get socket domain */
+#define SO_RERROR 0x1020 /* keep track of receive errors */
#endif
#if __BSD_VISIBLE
Index: sys/sys/socketvar.h
===================================================================
--- sys/sys/socketvar.h
+++ sys/sys/socketvar.h
@@ -100,6 +100,7 @@
struct protosw *so_proto; /* (a) protocol handle */
short so_timeo; /* (g) connection timeout */
u_short so_error; /* (f) error affecting connection */
+ u_short so_rerror; /* (f) error affecting connection */
struct sigio *so_sigio; /* [sg] information for async I/O or
out of band data (SIGURG) */
struct ucred *so_cred; /* (a) user credentials */
@@ -266,7 +267,8 @@
/* can we read something from so? */
#define soreadabledata(so) \
- (sbavail(&(so)->so_rcv) >= (so)->so_rcv.sb_lowat || (so)->so_error)
+ (sbavail(&(so)->so_rcv) >= (so)->so_rcv.sb_lowat || \
+ (so)->so_error || (so)->so_rerror)
#define soreadable(so) \
(soreadabledata(so) || ((so)->so_rcv.sb_state & SBS_CANTRCVMORE))
@@ -480,6 +482,8 @@
void socantrcvmore_locked(struct socket *so);
void socantsendmore(struct socket *so);
void socantsendmore_locked(struct socket *so);
+void soroverflow(struct socket *so);
+void soroverflow_locked(struct socket *so);
/*
* Accept filter functions (duh).

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 11, 8:51 AM (52 m, 27 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25151514
Default Alt Text
D26652.id77847.diff (12 KB)

Event Timeline