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
This commit is contained in:
ganglv 2022-09-17 06:08:10 +08:00 committed by GitHub
parent a1b50cac41
commit 5650762f2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 0 deletions

View File

@ -0,0 +1,53 @@
From 0a2f9a62bceb90b0d30461add2e25c4ce7a24547 Mon Sep 17 00:00:00 2001
From: Thomas Markwalder <tmark@isc.org>
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

View File

@ -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