summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2021-3549.patch
blob: 4391db340a60e9b670e34fc2349acb0c10d348fa (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
From 1cfcf3004e1830f8fe9112cfcd15285508d2c2b7 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Thu, 11 Feb 2021 16:56:42 +1030
Subject: [PATCH] PR27290, PR27293, PR27295, various avr objdump fixes

Adds missing sanity checks for avr device info note, to avoid
potential buffer overflows.  Uses bfd_malloc_and_get_section for
sanity checking section size.

	PR 27290
	PR 27293
	PR 27295
	* od-elf32_avr.c (elf32_avr_get_note_section_contents): Formatting.
	Use bfd_malloc_and_get_section.
	(elf32_avr_get_note_desc): Formatting.  Return descsz.  Sanity
	check namesz.  Return NULL if descsz is too small.  Ensure
	string table is terminated.
	(elf32_avr_get_device_info): Formatting.  Add note_size param.
	Sanity check note.
	(elf32_avr_dump_mem_usage): Adjust to suit.

Upstream-Status: Backport
CVE: CVE-2021-3549
Signed-of-by: Armin Kuster <akuster@mvista.com>

---
 binutils/ChangeLog      | 14 +++++++++
 binutils/od-elf32_avr.c | 66 ++++++++++++++++++++++++++---------------
 2 files changed, 56 insertions(+), 24 deletions(-)

Index: git/binutils/od-elf32_avr.c
===================================================================
--- git.orig/binutils/od-elf32_avr.c
+++ git/binutils/od-elf32_avr.c
@@ -77,23 +77,29 @@ elf32_avr_filter (bfd *abfd)
   return bfd_get_flavour (abfd) == bfd_target_elf_flavour;
 }
 
-static char*
+static char *
 elf32_avr_get_note_section_contents (bfd *abfd, bfd_size_type *size)
 {
   asection *section;
+  bfd_byte *contents;
 
-  if ((section = bfd_get_section_by_name (abfd, ".note.gnu.avr.deviceinfo")) == NULL)
+  section = bfd_get_section_by_name (abfd, ".note.gnu.avr.deviceinfo");
+  if (section == NULL)
     return NULL;
 
-  *size = bfd_section_size (section);
-  char *contents = (char *) xmalloc (*size);
-  bfd_get_section_contents (abfd, section, contents, 0, *size);
+  if (!bfd_malloc_and_get_section (abfd, section, &contents))
+    {
+      free (contents);
+      contents = NULL;
+    }
 
-  return contents;
+  *size = bfd_section_size (section);
+  return (char *) contents;
 }
 
-static char* elf32_avr_get_note_desc (bfd *abfd, char *contents,
-        bfd_size_type size)
+static char *
+elf32_avr_get_note_desc (bfd *abfd, char *contents, bfd_size_type size,
+			 bfd_size_type *descsz)
 {
   Elf_External_Note *xnp = (Elf_External_Note *) contents;
   Elf_Internal_Note in;
@@ -107,42 +113,54 @@ static char* elf32_avr_get_note_desc (bf
   if (in.namesz > contents - in.namedata + size)
     return NULL;
 
+  if (in.namesz != 4 || strcmp (in.namedata, "AVR") != 0)
+    return NULL;
+
   in.descsz = bfd_get_32 (abfd, xnp->descsz);
   in.descdata = in.namedata + align_power (in.namesz, 2);
-  if (in.descsz != 0
-        && (in.descdata >= contents + size
-            || in.descsz > contents - in.descdata + size))
+  if (in.descsz < 6 * sizeof (uint32_t)
+      || in.descdata >= contents + size
+      || in.descsz > contents - in.descdata + size)
     return NULL;
 
-  if (strcmp (in.namedata, "AVR") != 0)
-    return NULL;
+  /* If the note has a string table, ensure it is 0 terminated.  */
+  if (in.descsz > 8 * sizeof (uint32_t))
+    in.descdata[in.descsz - 1] = 0;
 
+  *descsz = in.descsz;
   return in.descdata;
 }
 
 static void
 elf32_avr_get_device_info (bfd *abfd, char *description,
-        deviceinfo *device)
+			   bfd_size_type desc_size, deviceinfo *device)
 {
   if (description == NULL)
     return;
 
   const bfd_size_type memory_sizes = 6;
 
-  memcpy (device, description, memory_sizes * sizeof(uint32_t));
-  device->name = NULL;
+  memcpy (device, description, memory_sizes * sizeof (uint32_t));
+  desc_size -= memory_sizes * sizeof (uint32_t);
+  if (desc_size < 8)
+    return;
 
-  uint32_t *stroffset_table = ((uint32_t *) description) + memory_sizes;
+  uint32_t *stroffset_table = (uint32_t *) description + memory_sizes;
   bfd_size_type stroffset_table_size = bfd_get_32 (abfd, stroffset_table);
-  char *str_table = ((char *) stroffset_table) + stroffset_table_size;
 
   /* If the only content is the size itself, there's nothing in the table */
-  if (stroffset_table_size == 4)
+  if (stroffset_table_size < 8)
     return;
+  if (desc_size <= stroffset_table_size)
+    return;
+  desc_size -= stroffset_table_size;
 
   /* First entry is the device name index. */
   uint32_t device_name_index = bfd_get_32 (abfd, stroffset_table + 1);
+  if (device_name_index >= desc_size)
+    return;
 
+  char *str_table = (char *) stroffset_table + stroffset_table_size;
   device->name = str_table + device_name_index;
 }
 
@@ -183,7 +201,7 @@ static void
 elf32_avr_dump_mem_usage (bfd *abfd)
 {
   char *description = NULL;
-  bfd_size_type note_section_size = 0;
+  bfd_size_type sec_size, desc_size;
 
   deviceinfo device = { 0, 0, 0, 0, 0, 0, NULL };
   device.name = "Unknown";
@@ -192,13 +210,13 @@ elf32_avr_dump_mem_usage (bfd *abfd)
   bfd_size_type text_usage = 0;
   bfd_size_type eeprom_usage = 0;
 
-  char *contents = elf32_avr_get_note_section_contents (abfd,
-    &note_section_size);
+  char *contents = elf32_avr_get_note_section_contents (abfd, &sec_size);
 
   if (contents != NULL)
     {
-      description = elf32_avr_get_note_desc (abfd, contents, note_section_size);
-      elf32_avr_get_device_info (abfd, description, &device);
+      description = elf32_avr_get_note_desc (abfd, contents, sec_size,
+					     &desc_size);
+      elf32_avr_get_device_info (abfd, description, desc_size, &device);
     }
 
   elf32_avr_get_memory_usage (abfd, &text_usage, &data_usage,
Index: git/binutils/ChangeLog
===================================================================
--- git.orig/binutils/ChangeLog
+++ git/binutils/ChangeLog
@@ -1,3 +1,17 @@
+2021-02-11  Alan Modra  <amodra@gmail.com>
+
+       PR 27290
+       PR 27293
+       PR 27295
+       * od-elf32_avr.c (elf32_avr_get_note_section_contents): Formatting.
+       Use bfd_malloc_and_get_section.
+       (elf32_avr_get_note_desc): Formatting.  Return descsz.  Sanity
+       check namesz.  Return NULL if descsz is too small.  Ensure
+       string table is terminated.
+       (elf32_avr_get_device_info): Formatting.  Add note_size param.
+       Sanity check note.
+       (elf32_avr_dump_mem_usage): Adjust to suit.
+
 2020-02-01  Nick Clifton  <nickc@redhat.com>
 
 	* configure: Regenerate.