From: Mark Andrews Date: Tue, 1 May 2018 06:52:01 +0000 (+1000) Subject: ISC_SOCKEVENTATTR_TRUNC was not be set X-Git-Tag: v9.9.13rc1~24^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8c9d54c99c910f6bb9b8677aeb604df16740aeb7;p=thirdparty%2Fbind9.git ISC_SOCKEVENTATTR_TRUNC was not be set (cherry picked from commit 6bff1768cfeb156f05a3a6078d79afa9c98b29b3) --- diff --git a/CHANGES b/CHANGES index 9f399d8589f..5ee8fd4ee35 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +4950. [bug] ISC_SOCKEVENTATTR_TRUNC was not be set. [GL #238] + 4949. [bug] lib/isc/print.c failed to handle floating point output correctly. [GL #261] diff --git a/lib/isc/tests/socket_test.c b/lib/isc/tests/socket_test.c index d0e5b003982..51724b7e0ed 100644 --- a/lib/isc/tests/socket_test.c +++ b/lib/isc/tests/socket_test.c @@ -29,6 +29,8 @@ #include "../task_p.h" #include "isctest.h" +static isc_boolean_t recv_trunc; + /* * Helper functions */ @@ -52,6 +54,7 @@ event_done(isc_task_t *task, isc_event_t *event) { dev = (isc_socketevent_t *) event; completion->result = dev->result; completion->done = ISC_TRUE; + recv_trunc = ISC_TF((dev->attributes & ISC_SOCKEVENTATTR_TRUNC) != 0); isc_event_free(&event); } @@ -70,6 +73,45 @@ waitfor(completion_t *completion) { return (ISC_R_FAILURE); } +/* + * Backport from 9.10 lib/isc/unix/socket.c. + */ +static void +destroy_socketevent(isc_event_t *event) { + isc_socketevent_t *ev = (isc_socketevent_t *)event; + + INSIST(ISC_LIST_EMPTY(ev->bufferlist)); + + (ev->destroy)(event); +} + +static isc_socketevent_t * +isc_socket_socketevent(isc_mem_t *mem, void *sender, + isc_eventtype_t eventtype, isc_taskaction_t action, + void *arg) +{ + isc_socketevent_t *ev; + + ev = (isc_socketevent_t *)isc_event_allocate(mem, sender, + eventtype, action, arg, + sizeof(*ev)); + + if (ev == NULL) + return (NULL); + + ev->result = ISC_R_UNSET; + ISC_LINK_INIT(ev, ev_link); + ISC_LIST_INIT(ev->bufferlist); + ev->region.base = NULL; + ev->n = 0; + ev->offset = 0; + ev->attributes = 0; + ev->destroy = ev->ev_destroy; + ev->ev_destroy = destroy_socketevent; + + return (ev); +} + /* * Individual unit tests */ @@ -242,12 +284,138 @@ ATF_TC_BODY(udp_dup, tc) { isc_test_end(); } +/* Test UDP truncation detection */ +ATF_TC(udp_trunc); +ATF_TC_HEAD(udp_trunc, tc) { + atf_tc_set_md_var(tc, "descr", "UDP Truncation detection"); +} +ATF_TC_BODY(udp_trunc, tc) { + isc_result_t result; + isc_sockaddr_t addr1, addr2; + struct in_addr in; + isc_socket_t *s1 = NULL, *s2 = NULL; + isc_task_t *task = NULL; + char sendbuf[BUFSIZ*2], recvbuf[BUFSIZ]; + completion_t completion; + isc_region_t r; + isc_socketevent_t *socketevent; + + UNUSED(tc); + + result = isc_test_begin(NULL, ISC_TRUE, 0); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + in.s_addr = inet_addr("127.0.0.1"); + isc_sockaddr_fromin(&addr1, &in, 0); + isc_sockaddr_fromin(&addr2, &in, 0); + + result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + result = isc_socket_getsockname(s1, &addr1); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + ATF_REQUIRE(isc_sockaddr_getport(&addr1) != 0); + + result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + result = isc_socket_getsockname(s2, &addr2); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + ATF_REQUIRE(isc_sockaddr_getport(&addr2) != 0); + + result = isc_task_create(taskmgr, 0, &task); + ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + + /* + * Send a message that will not be truncated. + */ + memset(sendbuf, 0xff, sizeof(sendbuf)); + snprintf(sendbuf, sizeof(sendbuf), "Hello"); + r.base = (void *) sendbuf; + r.length = strlen(sendbuf) + 1; + + completion_init(&completion); + + socketevent = isc_socket_socketevent(mctx, s1, ISC_SOCKEVENT_SENDDONE, + event_done, &completion); + ATF_REQUIRE(socketevent != NULL); + + result = isc_socket_sendto2(s1, &r, task, &addr2, NULL, socketevent, 0); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + waitfor(&completion); + ATF_CHECK(completion.done); + ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); + + r.base = (void *) recvbuf; + r.length = BUFSIZ; + completion_init(&completion); + recv_trunc = ISC_FALSE; + result = isc_socket_recv(s2, &r, 1, task, event_done, &completion); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + waitfor(&completion); + ATF_CHECK(completion.done); + ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); + ATF_CHECK_STREQ(recvbuf, "Hello"); + ATF_CHECK_EQ(recv_trunc, ISC_FALSE); + + /* + * Send a message that will be truncated. + */ + memset(sendbuf, 0xff, sizeof(sendbuf)); + snprintf(sendbuf, sizeof(sendbuf), "Hello"); + r.base = (void *) sendbuf; + r.length = sizeof(sendbuf); + + completion_init(&completion); + + socketevent = isc_socket_socketevent(mctx, s1, ISC_SOCKEVENT_SENDDONE, + event_done, &completion); + ATF_REQUIRE(socketevent != NULL); + + result = isc_socket_sendto2(s1, &r, task, &addr2, NULL, socketevent, 0); + ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "%s", + isc_result_totext(result)); + waitfor(&completion); + ATF_CHECK(completion.done); + ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); + + r.base = (void *) recvbuf; + r.length = BUFSIZ; + completion_init(&completion); + recv_trunc = ISC_FALSE; + result = isc_socket_recv(s2, &r, 1, task, event_done, &completion); + ATF_CHECK_EQ(result, ISC_R_SUCCESS); + waitfor(&completion); + ATF_CHECK(completion.done); + ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS); + ATF_CHECK_STREQ(recvbuf, "Hello"); + ATF_CHECK_EQ(recv_trunc, ISC_TRUE); + + isc_task_detach(&task); + + isc_socket_detach(&s1); + isc_socket_detach(&s2); + + isc_test_end(); +} + /* * Main */ ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, udp_sendto); ATF_TP_ADD_TC(tp, udp_dup); + ATF_TP_ADD_TC(tp, udp_trunc); return (atf_no_error()); } diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 8458cf47213..1c67b8f3ee7 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -341,7 +341,7 @@ struct isc__socket { bound : 1, /* bound to local addr */ dupped : 1; -#ifdef ISC_NET_RECVOVERFLOW +#ifdef ISC_PLATFORM_RECVOVERFLOW unsigned char overflow; /* used for MSG_TRUNC fake */ #endif @@ -432,7 +432,7 @@ static isc__socketmgr_t *socketmgr = NULL; * send() and recv() iovec counts */ #define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER) -#ifdef ISC_NET_RECVOVERFLOW +#ifdef ISC_PLATFORM_RECVOVERFLOW # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER + 1) #else # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) @@ -1517,10 +1517,6 @@ build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev, #else msg->msg_name = (void *)&dev->address.type.sa; msg->msg_namelen = sizeof(dev->address.type); -#endif -#ifdef ISC_NET_RECVOVERFLOW - /* If needed, steal one iovec for overflow detection. */ - maxiov--; #endif } else { /* TCP */ msg->msg_name = NULL; @@ -1572,12 +1568,11 @@ build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev, config: /* - * If needed, set up to receive that one extra byte. Note that - * we know there is at least one iov left, since we stole it - * at the top of this function. + * If needed, set up to receive that one extra byte. */ -#ifdef ISC_NET_RECVOVERFLOW +#ifdef ISC_PLATFORM_RECVOVERFLOW if (sock->type == isc_sockettype_udp) { + INSIST(iovcount < MAXSCATTERGATHER_RECV); iov[iovcount].iov_base = (void *)(&sock->overflow); iov[iovcount].iov_len = 1; iovcount++; @@ -1817,7 +1812,7 @@ doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) { * this indicates an overflow situation. Set the flag in the * dev entry and adjust how much we read by one. */ -#ifdef ISC_NET_RECVOVERFLOW +#ifdef ISC_PLATFORM_RECVOVERFLOW if ((sock->type == isc_sockettype_udp) && ((size_t)cc > read_count)) { dev->attributes |= ISC_SOCKEVENTATTR_TRUNC; cc--;