- GOOSE subscriber: fixed - possible heap corruption in parseAllData due to missing validity check in bit-string handling (LIB61850-402)

pull/457/head
Michael Zillgith 2 years ago
parent f951ebc08e
commit f41667367a

@ -263,6 +263,8 @@ void
Ethernet_addMulticastAddress(EthernetSocket ethSocket, uint8_t* multicastAddress) Ethernet_addMulticastAddress(EthernetSocket ethSocket, uint8_t* multicastAddress)
{ {
struct packet_mreq mreq; struct packet_mreq mreq;
memset(&mreq, 0, sizeof(struct packet_mreq));
mreq.mr_ifindex = ethSocket->socketAddress.sll_ifindex; mreq.mr_ifindex = ethSocket->socketAddress.sll_ifindex;
mreq.mr_alen = ETH_ALEN; mreq.mr_alen = ETH_ALEN;
mreq.mr_type = PACKET_MR_MULTICAST; mreq.mr_type = PACKET_MR_MULTICAST;

@ -194,6 +194,9 @@ StringUtils_copyStringMax(char* dest, int maxBufferSize, const char* str1)
{ {
char* res = dest; char* res = dest;
if (maxBufferSize < 1)
return NULL;
if (dest == NULL) if (dest == NULL)
res = (char*)GLOBAL_MALLOC(maxBufferSize); res = (char*)GLOBAL_MALLOC(maxBufferSize);

@ -210,13 +210,22 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
case 0x84: /* BIT STRING */ case 0x84: /* BIT STRING */
if (MmsValue_getType(value) == MMS_BIT_STRING) { if (MmsValue_getType(value) == MMS_BIT_STRING) {
int padding = buffer[bufPos]; int padding = buffer[bufPos];
int bitStringLength = (8 * (elementLength - 1)) - padding;
if (bitStringLength == value->value.bitString.size) { if (padding > 7) {
memcpy(value->value.bitString.buf, buffer + bufPos + 1, if (DEBUG_GOOSE_SUBSCRIBER)
elementLength - 1); printf("GOOSE_SUBSCRIBER: invalid bit-string (padding not plausible)\n");
pe = GOOSE_PARSE_ERROR_INVALID_PADDING;
} }
else { else {
pe = GOOSE_PARSE_ERROR_LENGTH_MISMATCH; int bitStringLength = (8 * (elementLength - 1)) - padding;
if (bitStringLength == value->value.bitString.size) {
memcpy(value->value.bitString.buf, buffer + bufPos + 1,
elementLength - 1);
}
else {
pe = GOOSE_PARSE_ERROR_LENGTH_MISMATCH;
}
} }
} }
else { else {
@ -352,7 +361,7 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
break; break;
} }
if ( pe != GOOSE_PARSE_ERROR_NO_ERROR ) { if (pe != GOOSE_PARSE_ERROR_NO_ERROR) {
break; /* from while */ break; /* from while */
} }
@ -362,14 +371,16 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
} }
if (elementIndex <= maxIndex) { if (elementIndex <= maxIndex) {
pe = GOOSE_PARSE_ERROR_UNDERFLOW; if (pe == GOOSE_PARSE_ERROR_NO_ERROR) {
pe = GOOSE_PARSE_ERROR_UNDERFLOW;
}
} }
if (DEBUG_GOOSE_SUBSCRIBER) { if (DEBUG_GOOSE_SUBSCRIBER) {
switch ( pe ) { switch (pe) {
case GOOSE_PARSE_ERROR_UNKNOWN_TAG: case GOOSE_PARSE_ERROR_UNKNOWN_TAG:
printf("GOOSE_SUBSCRIBER: Found unkown tag %02x!\n", tag); printf("GOOSE_SUBSCRIBER: Found unkown tag %02x!\n", tag);
break; break;
case GOOSE_PARSE_ERROR_TAGDECODE: case GOOSE_PARSE_ERROR_TAGDECODE:
printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n"); printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
break; break;
@ -388,6 +399,8 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
case GOOSE_PARSE_ERROR_LENGTH_MISMATCH: case GOOSE_PARSE_ERROR_LENGTH_MISMATCH:
printf("GOOSE_SUBSCRIBER: Message contains value of wrong length!\n"); printf("GOOSE_SUBSCRIBER: Message contains value of wrong length!\n");
break; break;
case GOOSE_PARSE_ERROR_INVALID_PADDING:
printf("GOOSE_SUBSCRIBER: Malformed message: invalid padding!\n");
default: default:
break; break;
} }
@ -500,7 +513,16 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
case 0x83: /* boolean */ case 0x83: /* boolean */
if (DEBUG_GOOSE_SUBSCRIBER) if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: found boolean\n"); printf("GOOSE_SUBSCRIBER: found boolean\n");
value = MmsValue_newBoolean(BerDecoder_decodeBoolean(buffer, bufPos));
if (elementLength > 0) {
value = MmsValue_newBoolean(BerDecoder_decodeBoolean(buffer, bufPos));
}
else {
if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: invalid length for boolean\n");
goto exit_with_error;
}
break; break;

@ -47,6 +47,7 @@ typedef enum
GOOSE_PARSE_ERROR_UNDERFLOW, GOOSE_PARSE_ERROR_UNDERFLOW,
GOOSE_PARSE_ERROR_TYPE_MISMATCH, GOOSE_PARSE_ERROR_TYPE_MISMATCH,
GOOSE_PARSE_ERROR_LENGTH_MISMATCH, GOOSE_PARSE_ERROR_LENGTH_MISMATCH,
GOOSE_PARSE_ERROR_INVALID_PADDING
} GooseParseError; } GooseParseError;
typedef struct sGooseSubscriber* GooseSubscriber; typedef struct sGooseSubscriber* GooseSubscriber;

@ -2205,7 +2205,7 @@ MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize)
const char* currentStr = MmsValue_printToBuffer((const MmsValue*) MmsValue_getElement(self, i), buffer + bufPos, bufferSize - bufPos); const char* currentStr = MmsValue_printToBuffer((const MmsValue*) MmsValue_getElement(self, i), buffer + bufPos, bufferSize - bufPos);
bufPos += strlen(currentStr); bufPos += strnlen(currentStr, bufferSize - bufPos);
if (bufPos >= bufferSize) if (bufPos >= bufferSize)
break; break;
@ -2240,9 +2240,13 @@ MmsValue_printToBuffer(const MmsValue* self, char* buffer, int bufferSize)
int size = MmsValue_getBitStringSize(self); int size = MmsValue_getBitStringSize(self);
/* fill buffer with zeros */ /* fill buffer with zeros */
if (size > bufferSize) { if (size + 1 > bufferSize) {
memset(buffer, 0, bufferSize); memset(buffer, 0, bufferSize);
break;
size = bufferSize - 1;
if (size < 1)
break;
} }
int i; int i;

Loading…
Cancel
Save