aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-kernel/ipmitool/ipmitool/0005-fru-sdr-Fix-id_string-buffer-overflows.patch
blob: cf8b9254c885b4d89f4115e38f445de6d62cdf86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
From 26e64ca78ae844c5ceedde89531e2924d7d4594c Mon Sep 17 00:00:00 2001
From: Chrostoper Ertl <chertl@microsoft.com>
Date: Thu, 28 Nov 2019 17:13:45 +0000
Subject: [PATCH 5/5] fru, sdr: Fix id_string buffer overflows

Final part of the fixes for CVE-2020-5208, see
https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp

9 variants of stack buffer overflow when parsing `id_string` field of
SDR records returned from `CMD_GET_SDR` command.

SDR record structs have an `id_code` field, and an `id_string` `char`
array.

The length of `id_string` is calculated as `(id_code & 0x1f) + 1`,
which can be larger than expected 16 characters (if `id_code = 0xff`,
then length will be `(0xff & 0x1f) + 1 = 32`).

In numerous places, this can cause stack buffer overflow when copying
into fixed buffer of size `17` bytes from this calculated length.

Upstream-Status: Backport[https://github.com/ipmitool/ipmitool/commit/7ccea283dd62a05a320c1921e3d8d71a87772637]
CVE: CVE-2020-5208

Signed-off-by: Wenlin Kang <wenlin.kang@windriver.com>
---
 lib/ipmi_fru.c |  2 +-
 lib/ipmi_sdr.c | 40 ++++++++++++++++++++++++----------------
 2 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
index b71ea23..1decea2 100644
--- a/lib/ipmi_fru.c
+++ b/lib/ipmi_fru.c
@@ -3038,7 +3038,7 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
 		return 0;
 
 	memset(desc, 0, sizeof(desc));
-	memcpy(desc, fru->id_string, fru->id_code & 0x01f);
+	memcpy(desc, fru->id_string, __min(fru->id_code & 0x01f, sizeof(desc)));
 	desc[fru->id_code & 0x01f] = 0;
 	printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
 
diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
index fa7b082..175a86f 100644
--- a/lib/ipmi_sdr.c
+++ b/lib/ipmi_sdr.c
@@ -2113,7 +2113,7 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
 		return -1;
 
 	memset(desc, 0, sizeof (desc));
-	snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string);
+	snprintf(desc, sizeof(desc), "%.*s", (sensor->id_code & 0x1f) + 1, sensor->id_string);
 
 	if (verbose) {
 		printf("Sensor ID              : %s (0x%x)\n",
@@ -2164,7 +2164,7 @@ ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf *intf,
 		return -1;
 
 	memset(desc, 0, sizeof (desc));
-	snprintf(desc, (mc->id_code & 0x1f) + 1, "%s", mc->id_string);
+	snprintf(desc, sizeof(desc), "%.*s", (mc->id_code & 0x1f) + 1, mc->id_string);
 
 	if (verbose == 0) {
 		if (csv_output)
@@ -2257,7 +2257,7 @@ ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf *intf,
 	char desc[17];
 
 	memset(desc, 0, sizeof (desc));
-	snprintf(desc, (dev->id_code & 0x1f) + 1, "%s", dev->id_string);
+	snprintf(desc, sizeof(desc), "%.*s", (dev->id_code & 0x1f) + 1, dev->id_string);
 
 	if (!verbose) {
 		if (csv_output)
@@ -2314,7 +2314,7 @@ ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf *intf,
 	char desc[17];
 
 	memset(desc, 0, sizeof (desc));
-	snprintf(desc, (fru->id_code & 0x1f) + 1, "%s", fru->id_string);
+	snprintf(desc, sizeof(desc), "%.*s", (fru->id_code & 0x1f) + 1, fru->id_string);
 
 	if (!verbose) {
 		if (csv_output)
@@ -2518,35 +2518,43 @@ ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf,uint16_t id,
 
    int rc =0;
    char desc[17];
+   const char *id_string;
+   uint8_t id_code;
    memset(desc, ' ', sizeof (desc));
 
    switch ( type) {
       case SDR_RECORD_TYPE_FULL_SENSOR:
       record.full = (struct sdr_record_full_sensor *) raw;
-      snprintf(desc, (record.full->id_code & 0x1f) +1, "%s",
-               (const char *)record.full->id_string);
+      id_code = record.full->id_code;
+      id_string = record.full->id_string;
       break;
+
       case SDR_RECORD_TYPE_COMPACT_SENSOR:
       record.compact = (struct sdr_record_compact_sensor *) raw	;
-      snprintf(desc, (record.compact->id_code & 0x1f)  +1, "%s",
-               (const char *)record.compact->id_string);
+      id_code = record.compact->id_code;
+      id_string = record.compact->id_string;
       break;
+
       case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
       record.eventonly  = (struct sdr_record_eventonly_sensor *) raw ;
-      snprintf(desc, (record.eventonly->id_code & 0x1f)  +1, "%s",
-               (const char *)record.eventonly->id_string);
-      break;            
+      id_code = record.eventonly->id_code;
+      id_string = record.eventonly->id_string;
+      break;
+
       case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
       record.mcloc  = (struct sdr_record_mc_locator *) raw ;
-      snprintf(desc, (record.mcloc->id_code & 0x1f)  +1, "%s",
-               (const char *)record.mcloc->id_string);		
+      id_code = record.mcloc->id_code;
+      id_string = record.mcloc->id_string;
       break;
+
       default:
       rc = -1;
-      break;
-   }   
+   }
+   if (!rc) {
+       snprintf(desc, sizeof(desc), "%.*s", (id_code & 0x1f) + 1, id_string);
+   }
 
-      lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
+   lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
    return rc;
 }
 
-- 
1.9.1