mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
Fix socket cmsg buffer usage
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,3 +1,6 @@
|
|||||||
|
4980. [bug] Fix race in cmsg buffer usage in socket code.
|
||||||
|
[GL #180]
|
||||||
|
|
||||||
4979. [bug] Named-checkconf failed to detect bad in-view targets.
|
4979. [bug] Named-checkconf failed to detect bad in-view targets.
|
||||||
[GL #288]
|
[GL #288]
|
||||||
|
|
||||||
|
@@ -375,9 +375,7 @@ struct isc__socket {
|
|||||||
unsigned char overflow; /* used for MSG_TRUNC fake */
|
unsigned char overflow; /* used for MSG_TRUNC fake */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *recvcmsgbuf;
|
|
||||||
ISC_SOCKADDR_LEN_T recvcmsgbuflen;
|
ISC_SOCKADDR_LEN_T recvcmsgbuflen;
|
||||||
char *sendcmsgbuf;
|
|
||||||
ISC_SOCKADDR_LEN_T sendcmsgbuflen;
|
ISC_SOCKADDR_LEN_T sendcmsgbuflen;
|
||||||
|
|
||||||
void *fdwatcharg;
|
void *fdwatcharg;
|
||||||
@@ -487,9 +485,9 @@ static void internal_send(isc_task_t *, isc_event_t *);
|
|||||||
static void internal_fdwatch_write(isc_task_t *, isc_event_t *);
|
static void internal_fdwatch_write(isc_task_t *, isc_event_t *);
|
||||||
static void internal_fdwatch_read(isc_task_t *, isc_event_t *);
|
static void internal_fdwatch_read(isc_task_t *, isc_event_t *);
|
||||||
static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *);
|
static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *);
|
||||||
static void build_msghdr_send(isc__socket_t *, isc_socketevent_t *,
|
static void build_msghdr_send(isc__socket_t *, char *, isc_socketevent_t *,
|
||||||
struct msghdr *, struct iovec *, size_t *);
|
struct msghdr *, struct iovec *, size_t *);
|
||||||
static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *,
|
static void build_msghdr_recv(isc__socket_t *, char *, isc_socketevent_t *,
|
||||||
struct msghdr *, struct iovec *, size_t *);
|
struct msghdr *, struct iovec *, size_t *);
|
||||||
#ifdef USE_WATCHER_THREAD
|
#ifdef USE_WATCHER_THREAD
|
||||||
static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager);
|
static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager);
|
||||||
@@ -1443,7 +1441,7 @@ process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
|
|||||||
* this transaction can send.
|
* this transaction can send.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
build_msghdr_send(isc__socket_t *sock, char* cmsgbuf, isc_socketevent_t *dev,
|
||||||
struct msghdr *msg, struct iovec *iov, size_t *write_countp)
|
struct msghdr *msg, struct iovec *iov, size_t *write_countp)
|
||||||
{
|
{
|
||||||
unsigned int iovcount;
|
unsigned int iovcount;
|
||||||
@@ -1456,8 +1454,9 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(msg, 0, sizeof(*msg));
|
memset(msg, 0, sizeof(*msg));
|
||||||
|
|
||||||
if (sock->sendcmsgbuflen != 0U) {
|
if (sock->sendcmsgbuflen != 0U) {
|
||||||
memset(sock->sendcmsgbuf, 0, sock->sendcmsgbuflen);
|
memset(cmsgbuf, 0, sock->sendcmsgbuflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sock->connected) {
|
if (!sock->connected) {
|
||||||
@@ -1536,11 +1535,11 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
"sendto pktinfo data, ifindex %u",
|
"sendto pktinfo data, ifindex %u",
|
||||||
dev->pktinfo.ipi6_ifindex);
|
dev->pktinfo.ipi6_ifindex);
|
||||||
|
|
||||||
msg->msg_control = (void *)sock->sendcmsgbuf;
|
msg->msg_control = (void *)cmsgbuf;
|
||||||
msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo));
|
msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo));
|
||||||
INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
|
INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
|
||||||
|
|
||||||
cmsgp = (struct cmsghdr *)sock->sendcmsgbuf;
|
cmsgp = (struct cmsghdr *)cmsgbuf;
|
||||||
cmsgp->cmsg_level = IPPROTO_IPV6;
|
cmsgp->cmsg_level = IPPROTO_IPV6;
|
||||||
cmsgp->cmsg_type = IPV6_PKTINFO;
|
cmsgp->cmsg_type = IPV6_PKTINFO;
|
||||||
cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
|
cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
|
||||||
@@ -1555,7 +1554,7 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
{
|
{
|
||||||
int use_min_mtu = 1; /* -1, 0, 1 */
|
int use_min_mtu = 1; /* -1, 0, 1 */
|
||||||
|
|
||||||
cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf +
|
cmsgp = (struct cmsghdr *)(cmsgbuf +
|
||||||
msg->msg_controllen);
|
msg->msg_controllen);
|
||||||
msg->msg_control = (void *)sock->sendcmsgbuf;
|
msg->msg_control = (void *)sock->sendcmsgbuf;
|
||||||
msg->msg_controllen += cmsg_space(sizeof(use_min_mtu));
|
msg->msg_controllen += cmsg_space(sizeof(use_min_mtu));
|
||||||
@@ -1585,9 +1584,9 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
|
|
||||||
#ifdef IP_TOS
|
#ifdef IP_TOS
|
||||||
if (sock->pf == AF_INET && sock->pktdscp) {
|
if (sock->pf == AF_INET && sock->pktdscp) {
|
||||||
cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf +
|
cmsgp = (struct cmsghdr *)(cmsgbuf +
|
||||||
msg->msg_controllen);
|
msg->msg_controllen);
|
||||||
msg->msg_control = (void *)sock->sendcmsgbuf;
|
msg->msg_control = (void *)cmsgbuf;
|
||||||
msg->msg_controllen += cmsg_space(sizeof(dscp));
|
msg->msg_controllen += cmsg_space(sizeof(dscp));
|
||||||
INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
|
INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
|
||||||
|
|
||||||
@@ -1616,9 +1615,9 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
#endif
|
#endif
|
||||||
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
|
#if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
|
||||||
if (sock->pf == AF_INET6 && sock->pktdscp) {
|
if (sock->pf == AF_INET6 && sock->pktdscp) {
|
||||||
cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf +
|
cmsgp = (struct cmsghdr *)(cmsgbuf +
|
||||||
msg->msg_controllen);
|
msg->msg_controllen);
|
||||||
msg->msg_control = (void *)sock->sendcmsgbuf;
|
msg->msg_control = (void *)cmsgbuf;
|
||||||
msg->msg_controllen += cmsg_space(sizeof(dscp));
|
msg->msg_controllen += cmsg_space(sizeof(dscp));
|
||||||
INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
|
INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
|
||||||
|
|
||||||
@@ -1647,7 +1646,7 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
if (msg->msg_controllen != 0 &&
|
if (msg->msg_controllen != 0 &&
|
||||||
msg->msg_controllen < sock->sendcmsgbuflen)
|
msg->msg_controllen < sock->sendcmsgbuflen)
|
||||||
{
|
{
|
||||||
memset(sock->sendcmsgbuf + msg->msg_controllen, 0,
|
memset(cmsgbuf + msg->msg_controllen, 0,
|
||||||
sock->sendcmsgbuflen - msg->msg_controllen);
|
sock->sendcmsgbuflen - msg->msg_controllen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1675,7 +1674,7 @@ build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
* this transaction can receive.
|
* this transaction can receive.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
|
build_msghdr_recv(isc__socket_t *sock, char *cmsgbuf, isc_socketevent_t *dev,
|
||||||
struct msghdr *msg, struct iovec *iov, size_t *read_countp)
|
struct msghdr *msg, struct iovec *iov, size_t *read_countp)
|
||||||
{
|
{
|
||||||
unsigned int iovcount;
|
unsigned int iovcount;
|
||||||
@@ -1773,7 +1772,7 @@ build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
|
|||||||
|
|
||||||
#ifdef ISC_NET_BSD44MSGHDR
|
#ifdef ISC_NET_BSD44MSGHDR
|
||||||
#if defined(USE_CMSG)
|
#if defined(USE_CMSG)
|
||||||
msg->msg_control = sock->recvcmsgbuf;
|
msg->msg_control = cmsgbuf;
|
||||||
msg->msg_controllen = sock->recvcmsgbuflen;
|
msg->msg_controllen = sock->recvcmsgbuflen;
|
||||||
#else
|
#else
|
||||||
msg->msg_control = NULL;
|
msg->msg_control = NULL;
|
||||||
@@ -1877,8 +1876,9 @@ doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) {
|
|||||||
isc_buffer_t *buffer;
|
isc_buffer_t *buffer;
|
||||||
int recv_errno;
|
int recv_errno;
|
||||||
char strbuf[ISC_STRERRORSIZE];
|
char strbuf[ISC_STRERRORSIZE];
|
||||||
|
char cmsgbuf[sock->recvcmsgbuflen];
|
||||||
|
|
||||||
build_msghdr_recv(sock, dev, &msghdr, iov, &read_count);
|
build_msghdr_recv(sock, cmsgbuf, dev, &msghdr, iov, &read_count);
|
||||||
|
|
||||||
#if defined(ISC_SOCKET_DEBUG)
|
#if defined(ISC_SOCKET_DEBUG)
|
||||||
dump_msg(&msghdr);
|
dump_msg(&msghdr);
|
||||||
@@ -2072,8 +2072,9 @@ doio_send(isc__socket_t *sock, isc_socketevent_t *dev) {
|
|||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
int send_errno;
|
int send_errno;
|
||||||
char strbuf[ISC_STRERRORSIZE];
|
char strbuf[ISC_STRERRORSIZE];
|
||||||
|
char cmsgbuf[sock->sendcmsgbuflen];
|
||||||
|
|
||||||
build_msghdr_send(sock, dev, &msghdr, iov, &write_count);
|
build_msghdr_send(sock, cmsgbuf, dev, &msghdr, iov, &write_count);
|
||||||
|
|
||||||
resend:
|
resend:
|
||||||
if (sock->type == isc_sockettype_udp &&
|
if (sock->type == isc_sockettype_udp &&
|
||||||
@@ -2312,11 +2313,8 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
|
|||||||
|
|
||||||
ISC_LINK_INIT(sock, link);
|
ISC_LINK_INIT(sock, link);
|
||||||
|
|
||||||
sock->recvcmsgbuf = NULL;
|
|
||||||
sock->sendcmsgbuf = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up cmsg buffers.
|
* Set up cmsg buffer lengths.
|
||||||
*/
|
*/
|
||||||
cmsgbuflen = 0;
|
cmsgbuflen = 0;
|
||||||
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
|
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
|
||||||
@@ -2329,13 +2327,6 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
|
|||||||
cmsgbuflen += cmsg_space(sizeof(int));
|
cmsgbuflen += cmsg_space(sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
sock->recvcmsgbuflen = cmsgbuflen;
|
sock->recvcmsgbuflen = cmsgbuflen;
|
||||||
if (sock->recvcmsgbuflen != 0U) {
|
|
||||||
sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
|
|
||||||
if (sock->recvcmsgbuf == NULL) {
|
|
||||||
result = ISC_R_NOMEMORY;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmsgbuflen = 0;
|
cmsgbuflen = 0;
|
||||||
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
|
#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
|
||||||
@@ -2352,13 +2343,6 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
|
|||||||
cmsgbuflen += cmsg_space(sizeof(int));
|
cmsgbuflen += cmsg_space(sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
sock->sendcmsgbuflen = cmsgbuflen;
|
sock->sendcmsgbuflen = cmsgbuflen;
|
||||||
if (sock->sendcmsgbuflen != 0U) {
|
|
||||||
sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
|
|
||||||
if (sock->sendcmsgbuf == NULL) {
|
|
||||||
result = ISC_R_NOMEMORY;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(sock->name, 0, sizeof(sock->name));
|
memset(sock->name, 0, sizeof(sock->name));
|
||||||
sock->tag = NULL;
|
sock->tag = NULL;
|
||||||
@@ -2406,12 +2390,6 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (sock->recvcmsgbuf != NULL)
|
|
||||||
isc_mem_put(manager->mctx, sock->recvcmsgbuf,
|
|
||||||
sock->recvcmsgbuflen);
|
|
||||||
if (sock->sendcmsgbuf != NULL)
|
|
||||||
isc_mem_put(manager->mctx, sock->sendcmsgbuf,
|
|
||||||
sock->sendcmsgbuflen);
|
|
||||||
isc_mem_put(manager->mctx, sock, sizeof(*sock));
|
isc_mem_put(manager->mctx, sock, sizeof(*sock));
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
@@ -2440,13 +2418,6 @@ free_socket(isc__socket_t **socketp) {
|
|||||||
INSIST(ISC_LIST_EMPTY(sock->connect_list));
|
INSIST(ISC_LIST_EMPTY(sock->connect_list));
|
||||||
INSIST(!ISC_LINK_LINKED(sock, link));
|
INSIST(!ISC_LINK_LINKED(sock, link));
|
||||||
|
|
||||||
if (sock->recvcmsgbuf != NULL)
|
|
||||||
isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf,
|
|
||||||
sock->recvcmsgbuflen);
|
|
||||||
if (sock->sendcmsgbuf != NULL)
|
|
||||||
isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
|
|
||||||
sock->sendcmsgbuflen);
|
|
||||||
|
|
||||||
sock->common.magic = 0;
|
sock->common.magic = 0;
|
||||||
sock->common.impmagic = 0;
|
sock->common.impmagic = 0;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user