forked from openwrt/packages
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request openwrt#12419 from lynxis/ipmitool
ipmitool: fix CVE-2020-5208
- Loading branch information
Showing
7 changed files
with
488 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 128 additions & 0 deletions
128
admin/ipmitool/patches/0006-CVE-2020-5208-fru-Fix-buffer-overflow-vulnerabilities.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
From 960dbb956d9f9cb05b719087faed53c88dc80956 Mon Sep 17 00:00:00 2001 | ||
From: Chrostoper Ertl <[email protected]> | ||
Date: Thu, 28 Nov 2019 16:33:59 +0000 | ||
Subject: [PATCH 06/11] fru: Fix buffer overflow vulnerabilities | ||
|
||
Partial fix for CVE-2020-5208, see | ||
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp | ||
|
||
The `read_fru_area_section` function only performs size validation of | ||
requested read size, and falsely assumes that the IPMI message will not | ||
respond with more than the requested amount of data; it uses the | ||
unvalidated response size to copy into `frubuf`. If the response is | ||
larger than the request, this can result in overflowing the buffer. | ||
|
||
The same issue affects the `read_fru_area` function. | ||
--- | ||
lib/ipmi_fru.c | 33 +++++++++++++++++++++++++++++++-- | ||
1 file changed, 31 insertions(+), 2 deletions(-) | ||
|
||
diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c | ||
index cf00effc82a2..af99aa99444c 100644 | ||
--- a/lib/ipmi_fru.c | ||
+++ b/lib/ipmi_fru.c | ||
@@ -615,7 +615,10 @@ int | ||
read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
uint32_t offset, uint32_t length, uint8_t *frubuf) | ||
{ | ||
- uint32_t off = offset, tmp, finish; | ||
+ uint32_t off = offset; | ||
+ uint32_t tmp; | ||
+ uint32_t finish; | ||
+ uint32_t size_left_in_buffer; | ||
struct ipmi_rs * rsp; | ||
struct ipmi_rq req; | ||
uint8_t msg_data[4]; | ||
@@ -628,10 +631,12 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
|
||
finish = offset + length; | ||
if (finish > fru->size) { | ||
+ memset(frubuf + fru->size, 0, length - fru->size); | ||
finish = fru->size; | ||
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, " | ||
"Adjusting to %d", | ||
offset + length, finish - offset); | ||
+ length = finish - offset; | ||
} | ||
|
||
memset(&req, 0, sizeof(req)); | ||
@@ -667,6 +672,7 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
} | ||
} | ||
|
||
+ size_left_in_buffer = length; | ||
do { | ||
tmp = fru->access ? off >> 1 : off; | ||
msg_data[0] = id; | ||
@@ -707,9 +713,18 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
} | ||
|
||
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0]; | ||
+ if(rsp->data_len < 1 | ||
+ || tmp > rsp->data_len - 1 | ||
+ || tmp > size_left_in_buffer) | ||
+ { | ||
+ printf(" Not enough buffer size"); | ||
+ return -1; | ||
+ } | ||
+ | ||
memcpy(frubuf, rsp->data + 1, tmp); | ||
off += tmp; | ||
frubuf += tmp; | ||
+ size_left_in_buffer -= tmp; | ||
/* sometimes the size returned in the Info command | ||
* is too large. return 0 so higher level function | ||
* still attempts to parse what was returned */ | ||
@@ -742,7 +757,9 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
uint32_t offset, uint32_t length, uint8_t *frubuf) | ||
{ | ||
static uint32_t fru_data_rqst_size = 20; | ||
- uint32_t off = offset, tmp, finish; | ||
+ uint32_t off = offset; | ||
+ uint32_t tmp, finish; | ||
+ uint32_t size_left_in_buffer; | ||
struct ipmi_rs * rsp; | ||
struct ipmi_rq req; | ||
uint8_t msg_data[4]; | ||
@@ -755,10 +772,12 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
|
||
finish = offset + length; | ||
if (finish > fru->size) { | ||
+ memset(frubuf + fru->size, 0, length - fru->size); | ||
finish = fru->size; | ||
lprintf(LOG_NOTICE, "Read FRU Area length %d too large, " | ||
"Adjusting to %d", | ||
offset + length, finish - offset); | ||
+ length = finish - offset; | ||
} | ||
|
||
memset(&req, 0, sizeof(req)); | ||
@@ -773,6 +792,8 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
if (fru->access && fru_data_rqst_size > 16) | ||
#endif | ||
fru_data_rqst_size = 16; | ||
+ | ||
+ size_left_in_buffer = length; | ||
do { | ||
tmp = fru->access ? off >> 1 : off; | ||
msg_data[0] = id; | ||
@@ -804,8 +825,16 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id, | ||
} | ||
|
||
tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0]; | ||
+ if(rsp->data_len < 1 | ||
+ || tmp > rsp->data_len - 1 | ||
+ || tmp > size_left_in_buffer) | ||
+ { | ||
+ printf(" Not enough buffer size"); | ||
+ return -1; | ||
+ } | ||
memcpy((frubuf + off)-offset, rsp->data + 1, tmp); | ||
off += tmp; | ||
+ size_left_in_buffer -= tmp; | ||
|
||
/* sometimes the size returned in the Info command | ||
* is too large. return 0 so higher level function | ||
-- | ||
2.27.0 | ||
|
48 changes: 48 additions & 0 deletions
48
...n/ipmitool/patches/0007-CVE-2020-5208-fru-Fix-buffer-overflow-in-ipmi_spd_print_fru.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
From 910e5782b7d9f222d4e34d3505d0d636ff757103 Mon Sep 17 00:00:00 2001 | ||
From: Chrostoper Ertl <[email protected]> | ||
Date: Thu, 28 Nov 2019 16:44:18 +0000 | ||
Subject: [PATCH 07/11] fru: Fix buffer overflow in ipmi_spd_print_fru | ||
|
||
Partial fix for CVE-2020-5208, see | ||
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp | ||
|
||
The `ipmi_spd_print_fru` function has a similar issue as the one fixed | ||
by the previous commit in `read_fru_area_section`. An initial request is | ||
made to get the `fru.size`, which is used as the size for the allocation | ||
of `spd_data`. Inside a loop, further requests are performed to get the | ||
copy sizes which are not checked before being used as the size for a | ||
copy into the buffer. | ||
--- | ||
lib/dimm_spd.c | 9 ++++++++- | ||
1 file changed, 8 insertions(+), 1 deletion(-) | ||
|
||
diff --git a/lib/dimm_spd.c b/lib/dimm_spd.c | ||
index 41e30dbb4bda..68f3b4fa1eff 100644 | ||
--- a/lib/dimm_spd.c | ||
+++ b/lib/dimm_spd.c | ||
@@ -1621,7 +1621,7 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id) | ||
struct ipmi_rq req; | ||
struct fru_info fru; | ||
uint8_t *spd_data, msg_data[4]; | ||
- int len, offset; | ||
+ uint32_t len, offset; | ||
|
||
msg_data[0] = id; | ||
|
||
@@ -1697,6 +1697,13 @@ ipmi_spd_print_fru(struct ipmi_intf * intf, uint8_t id) | ||
} | ||
|
||
len = rsp->data[0]; | ||
+ if(rsp->data_len < 1 | ||
+ || len > rsp->data_len - 1 | ||
+ || len > fru.size - offset) | ||
+ { | ||
+ printf(" Not enough buffer size"); | ||
+ return -1; | ||
+ } | ||
memcpy(&spd_data[offset], rsp->data + 1, len); | ||
offset += len; | ||
} while (offset < fru.size); | ||
-- | ||
2.27.0 | ||
|
48 changes: 48 additions & 0 deletions
48
...ool/patches/0008-CVE-2020-5208-session-Fix-buffer-overflow-in-ipmi_get_session_info.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
From 4f7778ed232a92bde388f38917b94f458a82c78e Mon Sep 17 00:00:00 2001 | ||
From: Chrostoper Ertl <[email protected]> | ||
Date: Thu, 28 Nov 2019 16:51:49 +0000 | ||
Subject: [PATCH 08/11] session: Fix buffer overflow in ipmi_get_session_info | ||
|
||
Partial fix for CVE-2020-5208, see | ||
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp | ||
|
||
The `ipmi_get_session_info` function does not properly check the | ||
response `data_len`, which is used as a copy size, allowing stack buffer | ||
overflow. | ||
--- | ||
lib/ipmi_session.c | 12 ++++++++---- | ||
1 file changed, 8 insertions(+), 4 deletions(-) | ||
|
||
diff --git a/lib/ipmi_session.c b/lib/ipmi_session.c | ||
index 141f0f4ec8dd..b9af1fd75d40 100644 | ||
--- a/lib/ipmi_session.c | ||
+++ b/lib/ipmi_session.c | ||
@@ -309,8 +309,10 @@ ipmi_get_session_info(struct ipmi_intf * intf, | ||
} | ||
else | ||
{ | ||
- memcpy(&session_info, rsp->data, rsp->data_len); | ||
- print_session_info(&session_info, rsp->data_len); | ||
+ memcpy(&session_info, rsp->data, | ||
+ __min(rsp->data_len, sizeof(session_info))); | ||
+ print_session_info(&session_info, | ||
+ __min(rsp->data_len, sizeof(session_info))); | ||
} | ||
break; | ||
|
||
@@ -341,8 +343,10 @@ ipmi_get_session_info(struct ipmi_intf * intf, | ||
break; | ||
} | ||
|
||
- memcpy(&session_info, rsp->data, rsp->data_len); | ||
- print_session_info(&session_info, rsp->data_len); | ||
+ memcpy(&session_info, rsp->data, | ||
+ __min(rsp->data_len, sizeof(session_info))); | ||
+ print_session_info(&session_info, | ||
+ __min(rsp->data_len, sizeof(session_info))); | ||
|
||
} while (i <= session_info.session_slot_count); | ||
break; | ||
-- | ||
2.27.0 | ||
|
37 changes: 37 additions & 0 deletions
37
admin/ipmitool/patches/0009-CVE-2020-5208-channel-Fix-buffer-overflow.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
From 743dd4faa302f22950e4438cf684e1e398eb47eb Mon Sep 17 00:00:00 2001 | ||
From: Chrostoper Ertl <[email protected]> | ||
Date: Thu, 28 Nov 2019 16:56:38 +0000 | ||
Subject: [PATCH 09/11] channel: Fix buffer overflow | ||
MIME-Version: 1.0 | ||
Content-Type: text/plain; charset=UTF-8 | ||
Content-Transfer-Encoding: 8bit | ||
|
||
Partial fix for CVE-2020-5208, see | ||
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp | ||
|
||
The `ipmi_get_channel_cipher_suites` function does not properly check | ||
the final response’s `data_len`, which can lead to stack buffer overflow | ||
on the final copy. | ||
--- | ||
lib/ipmi_channel.c | 5 ++++- | ||
1 file changed, 4 insertions(+), 1 deletion(-) | ||
|
||
diff --git a/lib/ipmi_channel.c b/lib/ipmi_channel.c | ||
index fab2e5483d12..8cd7c59a4273 100644 | ||
--- a/lib/ipmi_channel.c | ||
+++ b/lib/ipmi_channel.c | ||
@@ -413,7 +413,10 @@ ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type, | ||
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites"); | ||
return -1; | ||
} | ||
- if (rsp->ccode > 0) { | ||
+ if (rsp->ccode | ||
+ || rsp->data_len < 1 | ||
+ || rsp->data_len > sizeof(uint8_t) + 0x10) | ||
+ { | ||
lprintf(LOG_ERR, "Get Channel Cipher Suites failed: %s", | ||
val2str(rsp->ccode, completion_code_vals)); | ||
return -1; | ||
-- | ||
2.27.0 | ||
|
88 changes: 88 additions & 0 deletions
88
...mitool/patches/0010-CVE-2020-5208-lanp-Fix-buffer-overflows-in-get_lan_param_select.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
From e048e9c65a52f0879d482531e70735c1d314d43a Mon Sep 17 00:00:00 2001 | ||
From: Chrostoper Ertl <[email protected]> | ||
Date: Thu, 28 Nov 2019 17:06:39 +0000 | ||
Subject: [PATCH 10/11] lanp: Fix buffer overflows in get_lan_param_select | ||
MIME-Version: 1.0 | ||
Content-Type: text/plain; charset=UTF-8 | ||
Content-Transfer-Encoding: 8bit | ||
|
||
Partial fix for CVE-2020-5208, see | ||
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp | ||
|
||
The `get_lan_param_select` function is missing a validation check on the | ||
response’s `data_len`, which it then returns to caller functions, where | ||
stack buffer overflow can occur. | ||
--- | ||
lib/ipmi_lanp.c | 14 +++++++------- | ||
1 file changed, 7 insertions(+), 7 deletions(-) | ||
|
||
diff --git a/lib/ipmi_lanp.c b/lib/ipmi_lanp.c | ||
index 65d881bc5890..022c7f1605ed 100644 | ||
--- a/lib/ipmi_lanp.c | ||
+++ b/lib/ipmi_lanp.c | ||
@@ -1809,7 +1809,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, | ||
if (p == NULL) { | ||
return (-1); | ||
} | ||
- memcpy(data, p->data, p->data_len); | ||
+ memcpy(data, p->data, __min(p->data_len, sizeof(data))); | ||
/* set new ipaddr */ | ||
memcpy(data+3, temp, 4); | ||
printf("Setting LAN Alert %d IP Address to %d.%d.%d.%d\n", alert, | ||
@@ -1824,7 +1824,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, | ||
if (p == NULL) { | ||
return (-1); | ||
} | ||
- memcpy(data, p->data, p->data_len); | ||
+ memcpy(data, p->data, __min(p->data_len, sizeof(data))); | ||
/* set new macaddr */ | ||
memcpy(data+7, temp, 6); | ||
printf("Setting LAN Alert %d MAC Address to " | ||
@@ -1838,7 +1838,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, | ||
if (p == NULL) { | ||
return (-1); | ||
} | ||
- memcpy(data, p->data, p->data_len); | ||
+ memcpy(data, p->data, __min(p->data_len, sizeof(data))); | ||
|
||
if (strncasecmp(argv[1], "def", 3) == 0 || | ||
strncasecmp(argv[1], "default", 7) == 0) { | ||
@@ -1864,7 +1864,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, | ||
if (p == NULL) { | ||
return (-1); | ||
} | ||
- memcpy(data, p->data, p->data_len); | ||
+ memcpy(data, p->data, __min(p->data_len, sizeof(data))); | ||
|
||
if (strncasecmp(argv[1], "on", 2) == 0 || | ||
strncasecmp(argv[1], "yes", 3) == 0) { | ||
@@ -1889,7 +1889,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, | ||
if (p == NULL) { | ||
return (-1); | ||
} | ||
- memcpy(data, p->data, p->data_len); | ||
+ memcpy(data, p->data, __min(p->data_len, sizeof(data))); | ||
|
||
if (strncasecmp(argv[1], "pet", 3) == 0) { | ||
printf("Setting LAN Alert %d destination to PET Trap\n", alert); | ||
@@ -1917,7 +1917,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, | ||
if (p == NULL) { | ||
return (-1); | ||
} | ||
- memcpy(data, p->data, p->data_len); | ||
+ memcpy(data, p->data, __min(p->data_len, sizeof(data))); | ||
|
||
if (str2uchar(argv[1], &data[2]) != 0) { | ||
lprintf(LOG_ERR, "Invalid time: %s", argv[1]); | ||
@@ -1933,7 +1933,7 @@ ipmi_lan_alert_set(struct ipmi_intf * intf, uint8_t chan, uint8_t alert, | ||
if (p == NULL) { | ||
return (-1); | ||
} | ||
- memcpy(data, p->data, p->data_len); | ||
+ memcpy(data, p->data, __min(p->data_len, sizeof(data))); | ||
|
||
if (str2uchar(argv[1], &data[3]) != 0) { | ||
lprintf(LOG_ERR, "Invalid retry: %s", argv[1]); | ||
-- | ||
2.27.0 | ||
|
Oops, something went wrong.