This results in a segmentation fault / denial of service.
Breakpoint 2, Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:674
674 int len = 0;
(gdb) bt
#0 Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:674
#1 0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
#2 0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
#3 0x00005555556c10ae in Device_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/device.c:3500
#4 0x000055555574ceec in handler_write_property (service_request=0x5555562a7ba6 <Rx_Buf+6> "\f\a@", service_len=307, src=0x7ffff6000020, service_data=0x7ffff5d00420) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_wp.c:140
#5 0x000055555573c515 in apdu_handler (src=0x7ffff6000020, apdu=0x5555562a7ba2 <Rx_Buf+2> "", apdu_len=311) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_apdu.c:609
#6 0x00005555556ae5b6 in npdu_handler (src=0x7ffff6000020, pdu=0x5555562a7ba0 <Rx_Buf> "\001\004", pdu_len=313) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/npdu/h_npdu.c:279
#7 0x00005555556a5e3b in main (argc=3, argv=0x7fffffffe2a8) at /root/wc/bacnet/v1.5.0-verify/apps/server/main.c:423
(gdb) frame 0
#0 Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:674
674 int len = 0;
(gdb) info args
object_instance = 1
apdu = 0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>
apdu_size = 298
(gdb) list 676,681
676
677 pObject = Keylist_Data(Object_List, object_instance);
678 if (pObject) {
679 len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
680 }
681
(gdb) advance 679
Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
679 len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
(gdb) list 676,681
676
677 pObject = Keylist_Data(Object_List, object_instance);
678 if (pObject) {
679 len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
680 }
681
(gdb) print apdu_size
$1 = 298
(gdb) step
Breakpoint 1, bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:471
471 int apdu_len = 0;
(gdb) info args
apdu = 0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>
apdu_size = 298
value = 0x0
(gdb) bt
#0 bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:471
#1 0x0000555555722c61 in Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
#2 0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
#3 0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
#4 0x00005555556c10ae in Device_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/device.c:3500
#5 0x000055555574ceec in handler_write_property (service_request=0x5555562a7ba6 <Rx_Buf+6> "\f\a@", service_len=307, src=0x7ffff6000020, service_data=0x7ffff5d00420) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_wp.c:140
#6 0x000055555573c515 in apdu_handler (src=0x7ffff6000020, apdu=0x5555562a7ba2 <Rx_Buf+2> "", apdu_len=311) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_apdu.c:609
#7 0x00005555556ae5b6 in npdu_handler (src=0x7ffff6000020, pdu=0x5555562a7ba0 <Rx_Buf> "\001\004", pdu_len=313) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/npdu/h_npdu.c:279
#8 0x00005555556a5e3b in main (argc=3, argv=0x7fffffffe2a8) at /root/wc/bacnet/v1.5.0-verify/apps/server/main.c:423
(gdb) list 480,495
480 &apdu[apdu_len], apdu_size - apdu_len, 0, &object_type,
481 &object_instance);
482 if (len > 0) {
483 apdu_len += len;
484 if (value) {
485 value->deviceIdentifier.instance = object_instance;
486 value->deviceIdentifier.type = object_type;
487 }
488 } else if (len < 0) {
489 return BACNET_STATUS_ERROR;
490 } else {
491 /* OPTIONAL - skip apdu_len increment */
492 value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
493 value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
494 }
495 /* object-identifier [1] BACnetObjectIdentifier */
(gdb) tbreak /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
Temporary breakpoint 3 at 0x5555557f58d2: file /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c, line 492.
(gdb) c
Continuing.
Temporary breakpoint 3, bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492 value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) frame 0
#0 bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492 value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) info locals
len = 0
apdu_len = 0
object_type = OBJECT_ANALOG_INPUT
object_instance = 0
(gdb) print value
$2 = (BACNET_DEVICE_OBJECT_REFERENCE *) 0x0
(gdb) list 488,494
488 } else if (len < 0) {
489 return BACNET_STATUS_ERROR;
490 } else {
491 /* OPTIONAL - skip apdu_len increment */
492 value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
493 value->deviceIdentifier.instance = BACNET_NO_DEV_ID;
494 }
(gdb) list 472,481
472 BACNET_OBJECT_TYPE object_type = 0;
473 uint32_t object_instance = 0;
474
475 if (!apdu) {
476 return BACNET_STATUS_ERROR;
477 }
478 /* device-identifier [0] BACnetObjectIdentifier OPTIONAL */
479 len = bacnet_object_id_context_decode(
480 &apdu[apdu_len], apdu_size - apdu_len, 0, &object_type,
481 &object_instance);
(gdb) x/24xb apdu
0x7ffff6003830: 0x8f 0x07 0x01 0x2d 0x41 0x56 0x2d 0x31
0x7ffff6003838: 0x2d 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0x7ffff6003840: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
(gdb) print/x apdu[0]
$3 = 0x8f
(gdb) print/x apdu[1]
$4 = 0x7
(gdb) print/x apdu[2]
$5 = 0x1
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x00005555557f5916 in bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492 value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) bt
#0 0x00005555557f5916 in bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
#1 0x0000555555722c61 in Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
#2 0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
#3 0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
#4 0x00005555556c10ae in Device_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/device.c:3500
#5 0x000055555574ceec in handler_write_property (service_request=0x5555562a7ba6 <Rx_Buf+6> "\f\a@", service_len=307, src=0x7ffff6000020, service_data=0x7ffff5d00420) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_wp.c:140
#6 0x000055555573c515 in apdu_handler (src=0x7ffff6000020, apdu=0x5555562a7ba2 <Rx_Buf+2> "", apdu_len=311) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/service/h_apdu.c:609
#7 0x00005555556ae5b6 in npdu_handler (src=0x7ffff6000020, pdu=0x5555562a7ba0 <Rx_Buf> "\001\004", pdu_len=313) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/npdu/h_npdu.c:279
#8 0x00005555556a5e3b in main (argc=3, argv=0x7fffffffe2a8) at /root/wc/bacnet/v1.5.0-verify/apps/server/main.c:423
(gdb) frame 3
#3 0x0000555555721ac4 in Structured_View_Write_Property (wp_data=0x7ffff6003820) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:1668
1668 wp_data->error_code = bacnet_array_write(
(gdb) info args
wp_data = 0x7ffff6003820
(gdb) print *wp_data
$6 = {
object_instance = 1,
object_type = OBJECT_STRUCTURED_VIEW,
object_property = PROP_SUBORDINATE_LIST,
array_index = 4294967295,
application_data = "\217\a\001-AV-1-", 'A' <repeats 86 times>, "\000\000\000\002", 'A' <repeats 11 times>, "2", 'A' <repeats 18 times>, "\377", 'A' <repeats 19 times>, "0", 'A' <repeats 38 times>, "\020\000\000\000", 'A' <repeats 46 times>, "\276AAAAAAA\004\000\005:\016\f\001\300\000\001\036\tM\tU\t\b\t\b\t\b\t\t\t\t\t\b\t\t\t\t\t(AAAAAAAAA\200\000AAAAAAA;", '\000' <repeats 1177 times>,
application_data_len = 298,
priority = 16 '\020',
error_class = ERROR_CLASS_OBJECT,
error_code = ERROR_CODE_UNKNOWN_OBJECT
}
(gdb) list 1660,1670
1660 status = Structured_View_Represents_Set(
1661 wp_data->object_instance,
1662 &value.type.Device_Object_Reference);
1663 }
1664 break;
1665 case PROP_SUBORDINATE_LIST:
1666 array_size = Structured_View_Subordinate_List_Count(
1667 wp_data->object_instance);
1668 wp_data->error_code = bacnet_array_write(
1669 wp_data->object_instance, wp_data->array_index,
1670 Structured_View_Subordinate_List_Member_Decode,
(gdb) frame 2
#2 0x00005555557eb8cd in bacnet_array_write (object_instance=1, array_index=4294967295, decode_function=0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>, write_function=0x555555722c70 <Structured_View_Subordinate_List_Member_Write>, array_size=7, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdcode.c:5918
5918 len = decode_function(
(gdb) info args
object_instance = 1
array_index = 4294967295
decode_function = 0x555555722be0 <Structured_View_Subordinate_List_Member_Decode>
write_function = 0x555555722c70 <Structured_View_Subordinate_List_Member_Write>
array_size = 7
apdu = 0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>
apdu_size = 298
(gdb) list 5912,5922
5912 error_code = ERROR_CODE_ABORT_OTHER;
5913 }
5914 } else if (array_index == BACNET_ARRAY_ALL) {
5915 /* verify decoding of all elements */
5916 apdu_len = 0;
5917 for (index = 1; index <= array_size; index++) {
5918 len = decode_function(
5919 object_instance, &apdu[apdu_len], apdu_size - apdu_len);
5920 if (len >= 0) {
5921 apdu_len += len;
5922 } else {
(gdb) print array_index
$7 = 4294967295
(gdb) print apdu_size
$8 = 298
(gdb) frame 1
#1 0x0000555555722c61 in Structured_View_Subordinate_List_Member_Decode (object_instance=1, apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/basic/object/structured_view.c:679
679 len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
(gdb) list 674,680
674 int len = 0;
675 struct object_data *pObject;
676
677 pObject = Keylist_Data(Object_List, object_instance);
678 if (pObject) {
679 len = bacnet_device_object_reference_decode(apdu, apdu_size, NULL);
680 }
(gdb) list 680,686
680 }
681
682 return len;
683 }
684
685 /**
686 * @brief Write a value to a BACnetARRAY property element value
(gdb) frame 0
#0 0x00005555557f5916 in bacnet_device_object_reference_decode (apdu=0x7ffff6003830 "\217\a\001-AV-1-", 'A' <repeats 86 times>, apdu_size=298, value=0x0) at /root/wc/bacnet/v1.5.0-verify/src/bacnet/bacdevobjpropref.c:492
492 value->deviceIdentifier.type = BACNET_NO_DEV_TYPE;
(gdb) list 495,510
495 /* object-identifier [1] BACnetObjectIdentifier */
496 len = bacnet_object_id_context_decode(
497 &apdu[apdu_len], apdu_size - apdu_len, 1, &object_type,
498 &object_instance);
499 if (len > 0) {
500 apdu_len += len;
501 if (value) {
502 value->objectIdentifier.instance = object_instance;
503 value->objectIdentifier.type = object_type;
504 }
505 } else {
506 return BACNET_STATUS_ERROR;
507 }
508
509 return apdu_len;
510 }
The crash occurs exactly at that write.
Summary
A NULL pointer dereference can be triggered in
bacnet_device_object_reference_decode()when aWritePropertyrequest updatesOBJECT_STRUCTURED_VIEW/PROP_SUBORDINATE_LISTin bacnet-stackv1.5.0.The crash occurs because
Structured_View_Subordinate_List_Member_Decode()calls:and
bacnet_device_object_reference_decode()later writes tovalue->deviceIdentifierin thelen == 0branch even whenvalue == NULL.This results in a segmentation fault / denial of service.
Affected version
v1.5.0Impact
A crafted
WritePropertyrequest can cause the server application to crash, resulting in denial of service.Compile Command
Actual behavior if applicable
The outcome of ASAN
GDB outcome
Reproduce
poc:
poc.zip
replay program:
replay.zip
usage:
Root cause
The issue is caused by inconsistent handling of a NULL output pointer in
bacnet_device_object_reference_decode().Call chain:
Relevant code path in
structured_view.c:Relevant code path in
bacdevobjpropref.c:The
[0] device-identifierfield is optional. When it is absent,bacnet_object_id_context_decode(..., tag=0, ...)returnslen == 0, which is treated as an allowed condition. However, the else branch still unconditionally writes tovalue->deviceIdentifier.*, causing a NULL pointer dereference whenvalue == NULL.Trigger condition
The crash is reachable when processing a
WritePropertyrequest for:object_type = OBJECT_STRUCTURED_VIEWobject_property = PROP_SUBORDINATE_LISTarray_index = BACNET_ARRAY_ALLDuring validation of array members,
bacnet_array_write()calls the member decode function with the intent of checking decodability/length only, not storing the decoded structure. In that path,NULLis passed as the output pointer.If the subordinate-list member encoding omits the optional
[0] device-identifierbut still reachesbacnet_device_object_reference_decode(), thelen == 0branch dereferencesNULL.GDB confirmation
During debugging, the following conditions were confirmed:
Structured_View_Subordinate_List_Member_Decode()calls:bacnet_device_object_reference_decode():value == 0x0len == 0execution reaches:
The crash occurs exactly at that write.
Suggested fix
Guard the
len == 0branch withif (value)as well:An alternative defensive fix is to avoid passing
NULLfromStructured_View_Subordinate_List_Member_Decode()and instead decode into a temporary local structure.