port: fix buffer overflow in net_sync_resp_append()

The PortAddress structure has no space for the actual address and should
be used only as a pointer to a larger buffer.

The issue was reported by gcc with enabled source fortification.

[ RC: Replace magic number with sizeof() macro. ]

Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Miroslav Lichvar 2018-04-06 12:30:08 +02:00 committed by Richard Cochran
parent 74cdaafd5b
commit 73c4d9a3c7
1 changed files with 16 additions and 13 deletions

29
port.c
View File

@ -403,32 +403,35 @@ static int net_sync_resp_append(struct port *p, struct ptp_message *m)
struct port *best = clock_best_port(p->clock); struct port *best = clock_best_port(p->clock);
struct nsm_resp_tlv_head *head; struct nsm_resp_tlv_head *head;
struct Timestamp last_sync; struct Timestamp last_sync;
struct PortAddress paddr; struct PortAddress *paddr;
struct ptp_message *tmp; struct ptp_message *tmp;
struct tlv_extra *extra; struct tlv_extra *extra;
unsigned char *ptr; unsigned char *ptr;
int tlv_len; int tlv_len;
uint8_t buf[sizeof(*paddr) + sizeof(struct sockaddr_storage)];
last_sync = tmv_to_Timestamp(clock_ingress_time(p->clock)); last_sync = tmv_to_Timestamp(clock_ingress_time(p->clock));
pid = dad->pds.parentPortIdentity.clockIdentity; pid = dad->pds.parentPortIdentity.clockIdentity;
paddr = (struct PortAddress *)buf;
if (best && memcmp(&cid, &pid, sizeof(cid))) { if (best && memcmp(&cid, &pid, sizeof(cid))) {
/* Extract the parent's protocol address. */ /* Extract the parent's protocol address. */
paddr.networkProtocol = transport_type(best->trp); paddr->networkProtocol = transport_type(best->trp);
paddr.addressLength = paddr->addressLength =
transport_protocol_addr(best->trp, paddr.address); transport_protocol_addr(best->trp, paddr->address);
if (best->best) { if (best->best) {
tmp = TAILQ_FIRST(&best->best->messages); tmp = TAILQ_FIRST(&best->best->messages);
extract_address(tmp, &paddr); extract_address(tmp, paddr);
} }
} else { } else {
/* We are our own parent. */ /* We are our own parent. */
paddr.networkProtocol = transport_type(p->trp); paddr->networkProtocol = transport_type(p->trp);
paddr.addressLength = paddr->addressLength =
transport_protocol_addr(p->trp, paddr.address); transport_protocol_addr(p->trp, paddr->address);
} }
tlv_len = sizeof(*head) + sizeof(*extra->foot) + paddr.addressLength; tlv_len = sizeof(*head) + sizeof(*extra->foot) + paddr->addressLength;
extra = msg_tlv_append(m, tlv_len); extra = msg_tlv_append(m, tlv_len);
if (!extra) { if (!extra) {
@ -439,12 +442,12 @@ static int net_sync_resp_append(struct port *p, struct ptp_message *m)
head->type = TLV_PTPMON_RESP; head->type = TLV_PTPMON_RESP;
head->length = tlv_len - sizeof(head->type) - sizeof(head->length); head->length = tlv_len - sizeof(head->type) - sizeof(head->length);
head->port_state = p->state == PS_GRAND_MASTER ? PS_MASTER : p->state; head->port_state = p->state == PS_GRAND_MASTER ? PS_MASTER : p->state;
head->parent_addr.networkProtocol = paddr.networkProtocol; head->parent_addr.networkProtocol = paddr->networkProtocol;
head->parent_addr.addressLength = paddr.addressLength; head->parent_addr.addressLength = paddr->addressLength;
memcpy(head->parent_addr.address, paddr.address, paddr.addressLength); memcpy(head->parent_addr.address, paddr->address, paddr->addressLength);
ptr = (unsigned char *) head; ptr = (unsigned char *) head;
ptr += sizeof(*head) + paddr.addressLength; ptr += sizeof(*head) + paddr->addressLength;
extra->foot = (struct nsm_resp_tlv_foot *) ptr; extra->foot = (struct nsm_resp_tlv_foot *) ptr;
memcpy(&extra->foot->parent, &dad->pds, sizeof(extra->foot->parent)); memcpy(&extra->foot->parent, &dad->pds, sizeof(extra->foot->parent));