aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2017-15024.patch
blob: ef42b135970037647579ec821aaae21f13232bc3 (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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
commit 52a93b95ec0771c97e26f0bb28630a271a667bd2
Author: Alan Modra <amodra@gmail.com>
Date:   Sun Sep 24 14:37:16 2017 +0930

    PR22187, infinite loop in find_abstract_instance_name
    
    This patch prevents the simple case of infinite recursion in
    find_abstract_instance_name by ensuring that the attributes being
    processed are not the same as the previous call.
    
    The patch also does a little cleanup, and leaves in place some changes
    to the nested_funcs array that I made when I wrongly thought looping
    might occur in scan_unit_for_symbols.
    
    	PR 22187
    	* dwarf2.c (find_abstract_instance_name): Add orig_info_ptr and
    	pname param.  Return status.  Make name const.  Don't abort,
    	return an error.  Formatting.  Exit if current info_ptr matches
    	orig_info_ptr.  Update callers.
    	(scan_unit_for_symbols): Start at nesting_level of zero.  Make
    	nested_funcs an array of structs for extensibility.  Formatting.

Upstream-Status: Backport

CVE: CVE-2017-15024
Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com>

Index: git/bfd/dwarf2.c
===================================================================
--- git.orig/bfd/dwarf2.c	2017-11-08 12:44:59.198052588 +0530
+++ git/bfd/dwarf2.c	2017-11-08 12:45:10.670155730 +0530
@@ -2273,9 +2273,11 @@
     return FALSE;
 }
 
-static char *
+static bfd_boolean
 find_abstract_instance_name (struct comp_unit *unit,
+			     bfd_byte *orig_info_ptr,
 			     struct attribute *attr_ptr,
+			     const char **pname,
 			     bfd_boolean *is_linkage)
 {
   bfd *abfd = unit->abfd;
@@ -2285,7 +2287,7 @@
   struct abbrev_info *abbrev;
   bfd_uint64_t die_ref = attr_ptr->u.val;
   struct attribute attr;
-  char *name = NULL;
+  const char *name = NULL;
 
   /* DW_FORM_ref_addr can reference an entry in a different CU. It
      is an offset from the .debug_info section, not the current CU.  */
@@ -2294,7 +2296,12 @@
       /* We only support DW_FORM_ref_addr within the same file, so
 	 any relocations should be resolved already.  */
       if (!die_ref)
-	abort ();
+	{
+	  _bfd_error_handler
+	    (_("Dwarf Error: Abstract instance DIE ref zero."));
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
 
       info_ptr = unit->sec_info_ptr + die_ref;
       info_ptr_end = unit->end_ptr;
@@ -2329,9 +2336,10 @@
 	  (*_bfd_error_handler)
 	    (_("Dwarf Error: Unable to read alt ref %u."), die_ref);
 	  bfd_set_error (bfd_error_bad_value);
-	  return NULL;
+	  return FALSE;
 	}
-      info_ptr_end = unit->stash->alt_dwarf_info_buffer + unit->stash->alt_dwarf_info_size;
+      info_ptr_end = (unit->stash->alt_dwarf_info_buffer
+		      + unit->stash->alt_dwarf_info_size);
 
       /* FIXME: Do we need to locate the correct CU, in a similar
 	 fashion to the code in the DW_FORM_ref_addr case above ?  */
@@ -2353,6 +2361,7 @@
 	  (*_bfd_error_handler)
 	    (_("Dwarf Error: Could not find abbrev number %u."), abbrev_number);
 	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
 	}
       else
 	{
@@ -2362,6 +2371,15 @@
 					 info_ptr, info_ptr_end);
 	      if (info_ptr == NULL)
 		break;
+	      /* It doesn't ever make sense for DW_AT_specification to
+		 refer to the same DIE.  Stop simple recursion.  */
+	      if (info_ptr == orig_info_ptr)
+		{
+		  _bfd_error_handler
+		    (_("Dwarf Error: Abstract instance recursion detected."));
+		  bfd_set_error (bfd_error_bad_value);
+		  return FALSE;
+		}
 	      switch (attr.name)
 		{
 		case DW_AT_name:
@@ -2375,7 +2393,9 @@
 		    }
 		  break;
 		case DW_AT_specification:
-		  name = find_abstract_instance_name (unit, &attr, is_linkage);
+		  if (!find_abstract_instance_name (unit, info_ptr, &attr,
+						    pname, is_linkage))
+		    return FALSE;
 		  break;
 		case DW_AT_linkage_name:
 		case DW_AT_MIPS_linkage_name:
@@ -2393,7 +2413,8 @@
 	    }
 	}
     }
-  return name;
+  *pname = name;
+  return TRUE;
 }
 
 static bfd_boolean
@@ -2454,20 +2475,22 @@
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr = unit->first_child_die_ptr;
   bfd_byte *info_ptr_end = unit->stash->info_ptr_end;
-  int nesting_level = 1;
-  struct funcinfo **nested_funcs;
+  int nesting_level = 0;
+  struct nest_funcinfo {
+    struct funcinfo *func;
+  } *nested_funcs;
   int nested_funcs_size;
 
   /* Maintain a stack of in-scope functions and inlined functions, which we
      can use to set the caller_func field.  */
   nested_funcs_size = 32;
-  nested_funcs = (struct funcinfo **)
-    bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *));
+  nested_funcs = (struct nest_funcinfo *)
+    bfd_malloc (nested_funcs_size * sizeof (*nested_funcs));
   if (nested_funcs == NULL)
     return FALSE;
-  nested_funcs[nesting_level] = 0;
+  nested_funcs[nesting_level].func = 0;
 
-  while (nesting_level)
+  while (nesting_level >= 0)
     {
       unsigned int abbrev_number, bytes_read, i;
       struct abbrev_info *abbrev;
@@ -2516,13 +2539,13 @@
 	  BFD_ASSERT (!unit->cached);
 
 	  if (func->tag == DW_TAG_inlined_subroutine)
-	    for (i = nesting_level - 1; i >= 1; i--)
-	      if (nested_funcs[i])
+	    for (i = nesting_level; i-- != 0; )
+	      if (nested_funcs[i].func)
 		{
-		  func->caller_func = nested_funcs[i];
+		  func->caller_func = nested_funcs[i].func;
 		  break;
 		}
-	  nested_funcs[nesting_level] = func;
+	  nested_funcs[nesting_level].func = func;
 	}
       else
 	{
@@ -2541,12 +2564,13 @@
 	    }
 
 	  /* No inline function in scope at this nesting level.  */
-	  nested_funcs[nesting_level] = 0;
+	  nested_funcs[nesting_level].func = 0;
 	}
 
       for (i = 0; i < abbrev->num_attrs; ++i)
 	{
-	  info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, info_ptr_end);
+	  info_ptr = read_attribute (&attr, &abbrev->attrs[i],
+				     unit, info_ptr, info_ptr_end);
 	  if (info_ptr == NULL)
 	    goto fail;
 
@@ -2565,8 +2589,10 @@
 
 		case DW_AT_abstract_origin:
 		case DW_AT_specification:
-		  func->name = find_abstract_instance_name (unit, &attr,
-							    &func->is_linkage);
+		  if (!find_abstract_instance_name (unit, info_ptr, &attr,
+						    &func->name,
+						    &func->is_linkage))
+		    goto fail;
 		  break;
 
 		case DW_AT_name:
@@ -2691,17 +2717,17 @@
 
 	  if (nesting_level >= nested_funcs_size)
 	    {
-	      struct funcinfo **tmp;
+	      struct nest_funcinfo *tmp;
 
 	      nested_funcs_size *= 2;
-	      tmp = (struct funcinfo **)
+	      tmp = (struct nest_funcinfo *)
 		bfd_realloc (nested_funcs,
-			     nested_funcs_size * sizeof (struct funcinfo *));
+			     nested_funcs_size * sizeof (*nested_funcs));
 	      if (tmp == NULL)
 		goto fail;
 	      nested_funcs = tmp;
 	    }
-	  nested_funcs[nesting_level] = 0;
+	  nested_funcs[nesting_level].func = 0;
 	}
     }
 
Index: git/bfd/ChangeLog
===================================================================
--- git.orig/bfd/ChangeLog	2017-11-08 12:45:10.614155229 +0530
+++ git/bfd/ChangeLog	2017-11-08 12:46:55.791054918 +0530
@@ -1,3 +1,13 @@
+2017-09-24  Alan Modra  <amodra@gmail.com>
+
+       PR 22187
+       * dwarf2.c (find_abstract_instance_name): Add orig_info_ptr and
+       pname param.  Return status.  Make name const.  Don't abort,
+       return an error.  Formatting.  Exit if current info_ptr matches
+       orig_info_ptr.  Update callers.
+       (scan_unit_for_symbols): Start at nesting_level of zero.  Make
+       nested_funcs an array of structs for extensibility.  Formatting.
+
 2017-09-22  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR binutils/22170