From 5650762f2c12b6228f4a1b643a7728f418f2d31f Mon Sep 17 00:00:00 2001 From: ganglv <88995770+ganglyu@users.noreply.github.com> Date: Sat, 17 Sep 2022 06:08:10 +0800 Subject: [PATCH] Fix dhcp option buffer issue (#12033) Why I did it Current isc-dhcp uses below code to remove DHCP option: memmove(sp, op, op[1] + 2); sp += op[1] + 2; sp points to the option to be stripped, we can call it as option S. op points to the option after options S, we can call it as option O. DHCP option is a typical type-length-value structure, the first byte is type, the second byte is length, and remain parts are value. In this case, option O length is bigger than option S, and more than 2 bytes, after the memmove, we will get this result: Now Option S and Option O are overwritten, op[1] was the length of Option O, and it's modified after memmove. But current implementation is still using op[1] as length to update sp (sp+=op[1]+2), so we get the wrong sp. How I did it Create patch from https://github.com/isc-projects/dhcp The new impelementation use mlen to store the length of Option O before memmove, that's how it fixed the bug. size_t mlen = op[1] + 2; memmove(sp, op, mlen); sp += mlen; How to verify it I have a PR for sonic-mgmt to cover this issue: sonic-net/sonic-mgmt#6330 Signed-off-by: Gang Lv ganglv@microsoft.com --- ...ay-agent-option-buffer-pointer-logic.patch | 53 +++++++++++++++++++ src/isc-dhcp/patch/series | 1 + 2 files changed, 54 insertions(+) create mode 100644 src/isc-dhcp/patch/0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch diff --git a/src/isc-dhcp/patch/0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch b/src/isc-dhcp/patch/0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch new file mode 100644 index 0000000000..051b58966c --- /dev/null +++ b/src/isc-dhcp/patch/0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch @@ -0,0 +1,53 @@ +From 0a2f9a62bceb90b0d30461add2e25c4ce7a24547 Mon Sep 17 00:00:00 2001 +From: Thomas Markwalder +Date: Fri, 20 Dec 2019 10:11:54 -0500 +Subject: [PATCH] [#71] Fix dhcrelay agent option buffer pointer logic + +relay/dhcrelay.c + strip_relay_agent_options() + strip_relay_agent_options() + - corrected buffer pointer logic + +--- + relay/dhcrelay.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 896e1e2e..980dacae 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -1238,8 +1238,13 @@ strip_relay_agent_options(struct interface_info *in, + return (0); + + if (sp != op) { +- memmove(sp, op, op[1] + 2); +- sp += op[1] + 2; ++ size_t mlen = op[1] + 2; ++ memmove(sp, op, mlen); ++ sp += mlen; ++ if (sp > max) { ++ return (0); ++ } ++ + op = nextop; + } else + op = sp = nextop; +@@ -1620,8 +1620,13 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, + end_pad = NULL; + + if (sp != op) { +- memmove(sp, op, op[1] + 2); +- sp += op[1] + 2; ++ size_t mlen = op[1] + 2; ++ memmove(sp, op, mlen); ++ sp += mlen; ++ if (sp > max) { ++ return (0); ++ } ++ + op = nextop; + } else + op = sp = nextop; +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series index 5397aa0c6e..b9efee0192 100644 --- a/src/isc-dhcp/patch/series +++ b/src/isc-dhcp/patch/series @@ -11,3 +11,4 @@ 0010-Bugfix-correctly-set-interface-netmask.patch 0011-dhcp-relay-Prevent-Buffer-Overrun.patch 0012-add-option-si-to-support-using-src-intf-ip-in-relay.patch +0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch