Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F135500807
D26652.id77847.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D26652.id77847.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D26652: Implement SO_RERROR
Attached
Detach File
Event Timeline
Log In to Comment