mirror of
https://github.com/opnsense/src.git
synced 2026-06-17 04:29:12 -04:00
unix: fix EVFILT_WRITE when peer close(2)s and shutdown(2)s
For the close(2) case restore reporting the event with EV_EOF set. This fixes bug 286692. For the shutdown(2) case restore original behavior, but leave comment that we may want to change that. Thed157927807was not intended to bring in functional API changes. Provide tests for both cases. PR: 286692 Fixes:d157927807
This commit is contained in:
parent
d5566d7556
commit
eafe5967ac
2 changed files with 61 additions and 3 deletions
|
|
@ -1767,16 +1767,26 @@ uipc_filt_sowrite(struct knote *kn, long hint)
|
|||
struct socket *so = kn->kn_fp->f_data, *so2;
|
||||
struct unpcb *unp = sotounpcb(so), *unp2 = unp->unp_conn;
|
||||
|
||||
if (SOLISTENING(so) || unp2 == NULL)
|
||||
if (SOLISTENING(so))
|
||||
return (0);
|
||||
|
||||
if (unp2 == NULL) {
|
||||
if (so->so_state & SS_ISDISCONNECTED) {
|
||||
kn->kn_flags |= EV_EOF;
|
||||
kn->kn_fflags = so->so_error;
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
so2 = unp2->unp_socket;
|
||||
SOCK_RECVBUF_LOCK_ASSERT(so2);
|
||||
kn->kn_data = uipc_stream_sbspace(&so2->so_rcv);
|
||||
|
||||
if (so2->so_rcv.sb_state & SBS_CANTRCVMORE) {
|
||||
kn->kn_flags |= EV_EOF;
|
||||
kn->kn_fflags = so->so_error;
|
||||
/*
|
||||
* XXXGL: maybe kn->kn_flags |= EV_EOF ?
|
||||
*/
|
||||
return (1);
|
||||
} else if (kn->kn_sfflags & NOTE_LOWAT)
|
||||
return (kn->kn_data >= kn->kn_sdata);
|
||||
|
|
|
|||
|
|
@ -279,6 +279,52 @@ ATF_TC_BODY(unconnected_writability, tc)
|
|||
close(s);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(peerclosed_writability);
|
||||
ATF_TC_BODY(peerclosed_writability, tc)
|
||||
{
|
||||
struct kevent kev;
|
||||
int sv[2], kq;
|
||||
|
||||
do_socketpair(sv);
|
||||
close(sv[1]);
|
||||
|
||||
check_writable_select(sv[0], 1, false);
|
||||
check_writable_poll(sv[0], 1, false);
|
||||
|
||||
ATF_REQUIRE(kq = kqueue());
|
||||
EV_SET(&kev, sv[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL);
|
||||
ATF_REQUIRE(kevent(kq, &kev, 1, &kev, 1, NULL) == 1);
|
||||
ATF_REQUIRE(kev.ident == (uintptr_t)sv[0] &&
|
||||
kev.filter == EVFILT_WRITE &&
|
||||
kev.flags == EV_EOF);
|
||||
|
||||
close(sv[0]);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(peershutdown_writability);
|
||||
ATF_TC_BODY(peershutdown_writability, tc)
|
||||
{
|
||||
int sv[2];
|
||||
|
||||
do_socketpair(sv);
|
||||
shutdown(sv[1], SHUT_RD);
|
||||
|
||||
check_writable_select(sv[0], 1, false);
|
||||
check_writable_poll(sv[0], 1, false);
|
||||
/*
|
||||
* XXXGL: historically unix(4) sockets were not reporting peer's
|
||||
* shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says
|
||||
* "filter will set EV_EOF when the reader disconnects", which is hard
|
||||
* to interpret unambigously. For now leave the historic behavior,
|
||||
* but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(),
|
||||
* and then this test will look like the peerclosed_writability test.
|
||||
*/
|
||||
check_writable_kevent(sv[0], 1, false);
|
||||
|
||||
close(sv[0]);
|
||||
close(sv[1]);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
ATF_TP_ADD_TC(tp, getpeereid);
|
||||
|
|
@ -288,6 +334,8 @@ ATF_TP_ADD_TCS(tp)
|
|||
ATF_TP_ADD_TC(tp, full_writability_select);
|
||||
ATF_TP_ADD_TC(tp, full_writability_poll);
|
||||
ATF_TP_ADD_TC(tp, full_writability_kevent);
|
||||
ATF_TP_ADD_TC(tp, peerclosed_writability);
|
||||
ATF_TP_ADD_TC(tp, peershutdown_writability);
|
||||
|
||||
return atf_no_error();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue