Ilya Maximets <[email protected]> writes: > On 12/19/22 20:27, Aaron Conole wrote: >> From: Qian Chen <[email protected]> >> >> The OVS LLDP implementation includes support for AutoAttach standard, which >> the 'upstream' lldpd project does not include. As part of adding this >> support, the message parsing for these TLVs did not include proper length >> checks for the LLDP_TLV_AA_ELEMENT_SUBTYPE and the >> LLDP_TLV_AA_ISID_VLAN_ASGNS_SUBTYPE elements. The result is that a message >> without a proper boundary will cause an over read of memory, and lead to >> undefined results, including crashes or other unidentified behavior. >> >> The fix is to introduce proper bounds checking for these elements. Introduce >> a unit test to ensure that we have some proper rejection in this code >> base in the future. >> >> Fixes: be53a5c447c3 ("auto-attach: Initial support for Auto-Attach standard") >> Signed-off-by: Qian Chen <[email protected]> >> Co-authored-by: Aaron Conole <[email protected]> >> Signed-off-by: Aaron Conole <[email protected]> >> --- >> NOTES: This bug is publicly known and disclosed at >> https://github.com/openvswitch/ovs/pull/405 which makes this mostly >> a repost. >> I have modified the test case to ensure that it would run >> correctly when doing both 'make check-kernel' and >> 'make check-system-userspace' >> >> lib/lldp/lldp.c | 2 ++ >> tests/system-traffic.at | 27 +++++++++++++++++++++++++++ >> 2 files changed, 29 insertions(+) >> >> diff --git a/lib/lldp/lldp.c b/lib/lldp/lldp.c >> index dfeb2a8002..6fdcfef569 100644 >> --- a/lib/lldp/lldp.c >> +++ b/lib/lldp/lldp.c >> @@ -583,6 +583,7 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, >> int s, >> >> switch(tlv_subtype) { >> case LLDP_TLV_AA_ELEMENT_SUBTYPE: >> + CHECK_TLV_SIZE(50, "ELEMENT"); >> PEEK_BYTES(&msg_auth_digest, sizeof msg_auth_digest); >> >> aa_element_dword = PEEK_UINT32; >> @@ -629,6 +630,7 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, >> int s, >> break; >> >> case LLDP_TLV_AA_ISID_VLAN_ASGNS_SUBTYPE: >> + CHECK_TLV_SIZE(36, "ISID_VLAN_ASGNS"); >> PEEK_BYTES(&msg_auth_digest, sizeof msg_auth_digest); >> >> /* Subtract off tlv type and length (2Bytes) + OUI (3B) >> + >> diff --git a/tests/system-traffic.at b/tests/system-traffic.at >> index e5403519f2..0928bfe540 100644 >> --- a/tests/system-traffic.at >> +++ b/tests/system-traffic.at >> @@ -7440,3 +7440,30 @@ OVS_WAIT_UNTIL([cat p2.pcap | grep -E "0x0050: *0000 >> *0000 *5002 *2000 *b85e *00 >> >> OVS_TRAFFIC_VSWITCHD_STOP >> AT_CLEANUP >> + >> +AT_SETUP([autoattach - malformed lldp]) >> +OVS_TRAFFIC_VSWITCHD_START() >> + >> +ADD_NAMESPACES(at_ns0) >> + >> +dnl Set up simple bridge port to receive lldp packets >> +ADD_VETH(p0, at_ns0, br0, "172.31.1.1/24", "f6:b4:26:aa:5f:00") >> + >> +NETNS_DAEMONIZE([at_ns0], [tcpdump -l -n -xx -U -i p0 > p0.pcap], >> [tcpdump.pid]) >> +sleep 1 >> + >> +dnl Enable lldp >> +AT_CHECK([ovs-vsctl set interface ovs-p0 lldp:enable=true]) >> + >> +dnl Send a malformed lldp packet >> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 01 80 c2 00 00 0e >> f6 b4 26 aa 5f 00 88 cc 02 07 04 f6 b4 26 aa 5f 00 04 03 05 76 32 06 02 00 >> 78 0c 50 44 45 41 44 42 45 45 46 44 45 41 44 42 45 45 46 44 45 41 44 42 45 >> 45 46 44 45 41 44 42 45 45 46 44 45 41 44 42 45 45 46 44 45 41 44 42 45 45 >> 46 44 45 41 44 42 45 45 46 44 45 41 44 42 45 45 46 44 45 41 44 42 45 45 46 >> 44 45 41 44 42 45 45 46 fe 05 00 04 0d 0c 01 00 00 >/dev/null]) >> + >> +dnl Check the expected lldp packet by looking for the end >> +OVS_WAIT_UNTIL([cat p0.pcap | grep -E "0x0070: *4546 *fe05 *0004 *0d0c >> *0100 *00" 2>&1 1>/dev/null]) >> + >> +AT_CHECK([grep -o "ISID_VLAN_ASGNS TLV too short" ovs-vswitchd.log], [0], >> [dnl >> +ISID_VLAN_ASGNS TLV too short >> +]) >> + >> +OVS_TRAFFIC_VSWITCHD_STOP(["/|WARN|ISID_VLAN_ASGNS TLV too short received >> on ovs-p0/d"]) >> +AT_CLEANUP > > Do we actually need a system test here? > It looks like it can be converted to a simple unit test. E.g.: > > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > index eb4cd1896..41741d324 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -11966,3 +11966,25 @@ AT_CHECK([test 1 = `ovs-ofctl parse-pcap p2-tx.pcap > | wc -l`]) > > OVS_VSWITCHD_STOP > AT_CLEANUP > + > +AT_SETUP([ofproto-dpif - malformed lldp]) > +OVS_VSWITCHD_START > +add_of_ports br0 1 > + > +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) > + > +dnl Enable lldp. > +AT_CHECK([ovs-vsctl set interface p1 lldp:enable=true]) > + > +dnl Send a malformed lldp packet. > +packet="0180c200000ef6b426aa5f0088cc020704f6b426aa5f000403057632060200780c"dnl > +"5044454144424545464445414442454546444541444245454644454144424545464445414"dnl > +"4424545464445414442454546444541444245454644454144424545464445414442454546"dnl > +"4445414442454546fe0500040d0c010000" > +AT_CHECK([ovs-appctl netdev-dummy/receive p1 "$packet"], [0], [stdout]) > + > +dnl Check that the packet was flagged as invalid. > +OVS_WAIT_UNTIL([grep -q 'ISID_VLAN_ASGNS TLV too short' ovs-vswitchd.log]) > + > +OVS_VSWITCHD_STOP(["/|WARN|ISID_VLAN_ASGNS TLV too short received on p1/d"]) > +AT_CLEANUP > --- > > What do you think?
Makes sense to me. Submitting v2 now. > Best regards, Ilya Maximets. _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
