-
Notifications
You must be signed in to change notification settings - Fork 50
Description
[2025-12-10 13:57:08 root@abcks5008i ~]# lldptool -t -n -i prd0 -V portDesc
Port Description TLV
DD=abck604,RU=1I=prd0,CAB=ABC1-2604,RU=1
[2025-12-10 13:57:09 root@abcks5008i ~]# lldptool -t -n -i prd0 | grep -A1 'Port Description TLV'
Port Description TLV
DD=abcks5008i,DI=prd0,CAB=ABC1-2604,RU=1
[2025-12-10 13:57:23 root@abcks5008i ~]#
This issue does not happen on all servers, but it does happen on a few.
Above, notice a Rocky9 server with hostname 'abcks5008i'.
We configure the server's hostname in the switch's port description.
So we expect to see that string when querying the portDesc tlvid.
You can see that if that tlvid is queried directly, the hostname is garbled up.
Instead, if we don't specify any tlvid, the hostname is correct.
I'll point out that through strace, I know the problem comes from lldpad and not lldptool (we receive corrupted data via the socket).
This minimal patch seems to resolve the issue.
I am not claiming this patch is correct, in fact it probably isn't, and the program may be leaking memory now.
I'm just saying I did some troubleshooting, and this seems to solve the issue for us.
$ git diff
diff --git a/lldp_8023.c b/lldp_8023.c
index 81bd4e5..2c76ed7 100644
--- a/lldp_8023.c
+++ b/lldp_8023.c
@@ -748,7 +748,7 @@ int ieee8023_rchange(struct port *port, struct lldp_agent *agent,
case LLDP_8023_LINK_AGGREGATION:
case LLDP_8023_MAXIMUM_FRAME_SIZE:
/* We don't need to store the TLV, so free it */
- free_unpkd_tlv(tlv);
+ // free_unpkd_tlv(tlv);
return TLV_OK;
case LLDP_8023_ADD_ETH_CAPS:
ieee8023_rchange_add_eth_caps(bd, ud, tlv->info + OUI_SUB_SIZE,
diff --git a/lldp_mand_cmds.c b/lldp_mand_cmds.c
index bfbe98f..a0fb8eb 100644
--- a/lldp_mand_cmds.c
+++ b/lldp_mand_cmds.c
@@ -695,7 +695,7 @@ int get_tlvs(struct cmd *cmd, char *rbuf, int rlen)
}
if (tlvid == cmd->tlvid) {
- memcpy(tlvs+moff, tlvs+off, sizeof(u16)+len);
+ memmove(tlvs+moff, tlvs+off, sizeof(u16)+len);
moff += sizeof(u16)+len;
}
How I prepared the program for debugging:
# source /opt/third/gcc-compat/15/enable
# ./bootstrap.sh
# sed -i '/#define realloc rpl_realloc/ s/^/#/' ./configure
# ./configure --enable-asan --enable-ubsan --prefix=/usr3
# make -j -k
# make install
Initially this was spotted (leading me to comment out the free):
=================================================================
==2610626==ERROR: AddressSanitizer: heap-use-after-free on address 0x7b6f1cce66b0 at pc 0x00000050a5f1 bp 0x7ffd00087640 sp 0x7ffd00087638
READ of size 1 at 0x7b6f1cce66b0 thread T0
#0 0x00000050a5f0 in ieee8021qaz_rchange /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_8021qaz.c:1961
#1 0x0000004759a8 in rxProcessFrame lldp/rx.c:415
#2 0x000000477e91 in process_rx_frame lldp/rx.c:596
#3 0x000000477e91 in run_rx_sm lldp/rx.c:492
#4 0x00000047873b in rxReceiveFrame lldp/rx.c:124
#5 0x00000046abb1 in l2_packet_receive lldp/l2_packet_linux.c:154
#6 0x000000423d34 in eloop_sock_table_dispatch /<sanitized>/<sanitized>/git-ext/intel_openlldp/eloop.c:228
#7 0x000000426815 in eloop_run /<sanitized>/<sanitized>/git-ext/intel_openlldp/eloop.c:546
#8 0x00000040d50f in main /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldpad.c:466
#9 0x7f4f1dc2958f in __libc_start_call_main (/lib64/libc.so.6+0x2958f) (BuildId: 8c3b90b6dfac32e7e7da24c75b450ef3be7d48da)
#10 0x7f4f1dc2963f in __libc_start_main_alias_1 (/lib64/libc.so.6+0x2963f) (BuildId: 8c3b90b6dfac32e7e7da24c75b450ef3be7d48da)
#11 0x00000040e194 in _start (/usr3/sbin/lldpad+0x40e194) (BuildId: c06caa0ea312187561bb4c95bad2094ac791cdd7)
0x7b6f1cce66b0 is located 0 bytes inside of 16-byte region [0x7b6f1cce66b0,0x7b6f1cce66c0)
freed by thread T0 here:
#0 0x7f4f1e91d29b in free /opt/tmp/gcc-15.2.0/libsanitizer/asan/asan_malloc_linux.cpp:51
#1 0x0000004f55b8 in ieee8023_rchange /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_8023.c:751
previously allocated by thread T0 here:
#0 0x7f4f1e91df53 in calloc /opt/tmp/gcc-15.2.0/libsanitizer/asan/asan_malloc_linux.cpp:74
#1 0x0000004e3102 in create_tlv /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_tlv.c:196
SUMMARY: AddressSanitizer: heap-use-after-free /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_8021qaz.c:1961 in ieee8021qaz_rchange
Shadow bytes around the buggy address:
0x7b6f1cce6400: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fa
0x7b6f1cce6480: fa fa 00 00 fa fa 07 fa fa fa 07 fa fa fa 00 00
0x7b6f1cce6500: fa fa 00 07 fa fa 00 07 fa fa 00 00 fa fa 02 fa
0x7b6f1cce6580: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
0x7b6f1cce6600: fa fa 04 fa fa fa 00 00 fa fa 00 04 fa fa fd fd
=>0x7b6f1cce6680: fa fa fd fa fa fa[fd]fd fa fa fd fd fa fa fa fa
0x7b6f1cce6700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7b6f1cce6780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7b6f1cce6800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7b6f1cce6880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7b6f1cce6900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==2610626==ABORTING
Then this was spotted, leading me to replace the memcpy with a memmove:
=================================================================
==2613082==ERROR: AddressSanitizer: memcpy-param-overlap: memory ranges [0x7b547582d040,0x7b547582d065) and [0x7b547582d05e, 0x7b547582d083) overlap
#0 0x7f547811bb2e in memcpy /opt/tmp/gcc-15.2.0/libsanitizer/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc:115
#1 0x0000004b2ac8 in memcpy /usr/include/bits/string_fortified.h:29
#2 0x0000004b2ac8 in get_tlvs /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_mand_cmds.c:698
#3 0x0000004b4bfe in mand_clif_cmd /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_mand_cmds.c:851
#4 0x00000041d061 in clif_iface_module /<sanitized>/<sanitized>/git-ext/intel_openlldp/ctrl_iface.c:119
#5 0x00000041db0a in process_clif_cmd /<sanitized>/<sanitized>/git-ext/intel_openlldp/ctrl_iface.c:323
#6 0x00000041db0a in ctrl_iface_receive /<sanitized>/<sanitized>/git-ext/intel_openlldp/ctrl_iface.c:400
#7 0x000000423d34 in eloop_sock_table_dispatch /<sanitized>/<sanitized>/git-ext/intel_openlldp/eloop.c:228
#8 0x000000426815 in eloop_run /<sanitized>/<sanitized>/git-ext/intel_openlldp/eloop.c:546
#9 0x00000040d50f in main /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldpad.c:466
#10 0x7f547742958f in __libc_start_call_main (/lib64/libc.so.6+0x2958f) (BuildId: 8c3b90b6dfac32e7e7da24c75b450ef3be7d48da)
#11 0x7f547742963f in __libc_start_main_alias_1 (/lib64/libc.so.6+0x2963f) (BuildId: 8c3b90b6dfac32e7e7da24c75b450ef3be7d48da)
#12 0x00000040e194 in _start (/usr3/sbin/lldpad+0x40e194) (BuildId: 537d047e76b7b5d9794cd45dd8166fe2de4c84d2)
Address 0x7b547582d040 is located in stack of thread T0 at offset 64 in frame
#0 0x0000004b270f in get_tlvs /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_mand_cmds.c:657
This frame has 2 object(s):
[48, 52) 'size' (line 659)
[64, 2112) 'tlvs' (line 658) <== Memory access at offset 64 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
Address 0x7b547582d05e is located in stack of thread T0 at offset 94 in frame
#0 0x0000004b270f in get_tlvs /<sanitized>/<sanitized>/git-ext/intel_openlldp/lldp_mand_cmds.c:657
This frame has 2 object(s):
[48, 52) 'size' (line 659)
[64, 2112) 'tlvs' (line 658) <== Memory access at offset 94 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: memcpy-param-overlap /usr/include/bits/string_fortified.h:29 in memcpy
==2613082==ABORTING