aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2017-15938.patch
blob: 25d6f3a32a08e21c00554c27018d6f9ea7a91845 (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
commit 1b86808a86077722ee4f42ff97f836b12420bb2a
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Sep 26 21:47:24 2017 +0930

    PR22209, invalid memory read in find_abstract_instance_name
    
    This patch adds bounds checking for DW_FORM_ref_addr die refs, and
    calculates them relative to the first .debug_info section.  See the
    big comment for why calculating relative to the current .debug_info
    section was wrong for relocatable object files.
    
    	PR 22209
    	* dwarf2.c (struct comp_unit): Delete sec_info_ptr field.
    	(find_abstract_instance_name): Calculate DW_FORM_ref_addr relative
    	to stash->info_ptr_memory, and check die_ref is within that memory.
    	Set info_ptr_end correctly when another CU is refd.  Check die_ref
    	for DW_FORM_ref4 etc. is within CU.

Upstream-Status: Backport

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

Index: git/bfd/dwarf2.c
===================================================================
--- git.orig/bfd/dwarf2.c	2017-11-07 18:52:19.896253364 +0530
+++ git/bfd/dwarf2.c	2017-11-07 18:52:19.952253802 +0530
@@ -119,8 +119,7 @@
 
   /* A pointer to the memory block allocated for info_ptr.  Neither
      info_ptr nor sec_info_ptr are guaranteed to stay pointing to the
-     beginning of the malloc block.  This is used only to free the
-     memory later.  */
+     beginning of the malloc block.  */
   bfd_byte *info_ptr_memory;
 
   /* Pointer to the symbol table.  */
@@ -238,9 +237,6 @@
      by its reference.  */
   bfd_byte *info_ptr_unit;
 
-  /* Pointer to the start of the debug section, for DW_FORM_ref_addr.  */
-  bfd_byte *sec_info_ptr;
-
   /* The offset into .debug_line of the line number table.  */
   unsigned long line_offset;
 
@@ -2294,21 +2290,37 @@
   if (attr_ptr->form == DW_FORM_ref_addr)
     {
       /* We only support DW_FORM_ref_addr within the same file, so
-	 any relocations should be resolved already.  */
-      if (!die_ref)
+	 any relocations should be resolved already.  Check this by
+	 testing for a zero die_ref;  There can't be a valid reference
+	 to the header of a .debug_info section.
+	 DW_FORM_ref_addr is an offset relative to .debug_info.
+	 Normally when using the GNU linker this is accomplished by
+	 emitting a symbolic reference to a label, because .debug_info
+	 sections are linked at zero.  When there are multiple section
+	 groups containing .debug_info, as there might be in a
+	 relocatable object file, it would be reasonable to assume that
+	 a symbolic reference to a label in any .debug_info section
+	 might be used.  Since we lay out multiple .debug_info
+	 sections at non-zero VMAs (see place_sections), and read
+	 them contiguously into stash->info_ptr_memory, that means
+	 the reference is relative to stash->info_ptr_memory.  */
+      size_t total;
+
+      info_ptr = unit->stash->info_ptr_memory;
+      info_ptr_end = unit->stash->info_ptr_end;
+      total = info_ptr_end - info_ptr;
+      if (!die_ref || die_ref >= total)
 	{
 	  _bfd_error_handler
-	    (_("Dwarf Error: Abstract instance DIE ref zero."));
+	    (_("Dwarf Error: Invalid abstract instance DIE ref."));
 	  bfd_set_error (bfd_error_bad_value);
 	  return FALSE;
 	}
-
-      info_ptr = unit->sec_info_ptr + die_ref;
-      info_ptr_end = unit->end_ptr;
+      info_ptr += die_ref;
 
       /* Now find the CU containing this pointer.  */
       if (info_ptr >= unit->info_ptr_unit && info_ptr < unit->end_ptr)
-	;
+	info_ptr_end = unit->end_ptr;
       else
 	{
 	  /* Check other CUs to see if they contain the abbrev.  */
@@ -2324,7 +2336,10 @@
 		break;
 
 	  if (u)
-	    unit = u;
+	    {
+	      unit = u;
+	      info_ptr_end = unit->end_ptr;
+	    }
 	  /* else FIXME: What do we do now ?  */
 	}
     }
@@ -2346,8 +2361,22 @@
     }
   else
     {
-      info_ptr = unit->info_ptr_unit + die_ref;
+      /* DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8 or
+	 DW_FORM_ref_udata.  These are all references relative to the
+	 start of the current CU.  */
+      size_t total;
+
+      info_ptr = unit->info_ptr_unit;
       info_ptr_end = unit->end_ptr;
+      total = info_ptr_end - info_ptr;
+      if (!die_ref || die_ref >= total)
+	{
+	  _bfd_error_handler
+	    (_("Dwarf Error: Invalid abstract instance DIE ref."));
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+      info_ptr += die_ref;
     }
 
   abbrev_number = safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end);
@@ -2846,7 +2875,6 @@
   unit->end_ptr = end_ptr;
   unit->stash = stash;
   unit->info_ptr_unit = info_ptr_unit;
-  unit->sec_info_ptr = stash->sec_info_ptr;
 
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
Index: git/bfd/ChangeLog
===================================================================
--- git.orig/bfd/ChangeLog	2017-11-07 18:52:19.900253395 +0530
+++ git/bfd/ChangeLog	2017-11-07 18:53:29.668799630 +0530
@@ -1,3 +1,12 @@
+2017-09-26  Alan Modra  <amodra@gmail.com>
+
+       PR 22209
+       * dwarf2.c (struct comp_unit): Delete sec_info_ptr field.
+       (find_abstract_instance_name): Calculate DW_FORM_ref_addr relative
+       to stash->info_ptr_memory, and check die_ref is within that memory.
+       Set info_ptr_end correctly when another CU is refd.  Check die_ref
+       for DW_FORM_ref4 etc. is within CU.
+
 2017-09-24  Alan Modra  <amodra@gmail.com>
 
        PR 22187