Add .note.gnu.property runtime verification and merge support
[external/binutils.git] / bfd / elf-properties.c
1 /* ELF program property support.
2    Copyright (C) 2017 Free Software Foundation, Inc.
3
4    This file is part of BFD, the Binary File Descriptor library.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 /* GNU program property draft is at:
22
23    https://github.com/hjl-tools/linux-abi/wiki/property-draft.pdf
24  */
25
26 #include "sysdep.h"
27 #include "bfd.h"
28 #include "libbfd.h"
29 #include "elf-bfd.h"
30
31 /* Get a property, allocate a new one if needed.  */
32
33 elf_property *
34 _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz)
35 {
36   elf_property_list *p, **lastp;
37
38   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
39     {
40       /* Never should happen.  */
41       abort ();
42     }
43
44   /* Keep the property list in order of type.  */
45   lastp = &elf_properties (abfd);
46   for (p = *lastp; p; p = p->next)
47     {
48       /* Reuse the existing entry.  */
49       if (type == p->property.pr_type)
50         {
51           if (datasz > p->property.pr_datasz)
52             {
53               /* This can happen when mixing 32-bit and 64-bit objects.  */
54               p->property.pr_datasz = datasz;
55             }
56           return &p->property;
57         }
58       else if (type < p->property.pr_type)
59         break;
60       lastp = &p->next;
61     }
62   p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p));
63   if (p == NULL)
64     {
65       _bfd_error_handler (_("%B: out of memory in _bfd_elf_get_property"),
66                           abfd);
67       _exit (EXIT_FAILURE);
68     }
69   memset (p, 0, sizeof (*p));
70   p->property.pr_type = type;
71   p->property.pr_datasz = datasz;
72   p->property.filename = abfd->filename;
73   p->next = *lastp;
74   *lastp = p;
75   return &p->property;
76 }
77
78 /* Parse GNU properties.  */
79
80 bfd_boolean
81 _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note)
82 {
83   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
84   unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
85   bfd_byte *ptr = (bfd_byte *) note->descdata;
86   bfd_byte *ptr_end = ptr + note->descsz;
87
88   if (note->descsz < 8 || (note->descsz % align_size) != 0)
89     {
90 bad_size:
91       _bfd_error_handler
92         (_("warning: %B: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx\n"),
93          abfd, note->type, note->descsz);
94       return FALSE;
95     }
96
97   while (1)
98     {
99       unsigned int type = bfd_h_get_32 (abfd, ptr);
100       unsigned int datasz = bfd_h_get_32 (abfd, ptr + 4);
101       elf_property *prop;
102
103       ptr += 8;
104
105       if ((ptr + datasz) > ptr_end)
106         {
107           _bfd_error_handler
108             (_("warning: %B: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x\n"),
109              abfd, note->type, type, datasz);
110           /* Clear all properties.  */
111           elf_properties (abfd) = NULL;
112           return FALSE;
113         }
114
115       if (type >= GNU_PROPERTY_LOPROC)
116         {
117           if (type < GNU_PROPERTY_LOUSER && bed->parse_gnu_properties)
118             {
119               enum elf_property_kind kind
120                 = bed->parse_gnu_properties (abfd, type, ptr, datasz);
121               if (kind == property_corrupt)
122                 {
123                   /* Clear all properties.  */
124                   elf_properties (abfd) = NULL;
125                   return FALSE;
126                 }
127               else if (kind != property_ignored)
128                 goto next;
129             }
130         }
131       else
132         {
133           switch (type)
134             {
135             case GNU_PROPERTY_STACK_SIZE:
136               if (datasz != align_size)
137                 {
138                   _bfd_error_handler
139                     (_("warning: %B: corrupt stack size: 0x%x\n"),
140                      abfd, datasz);
141                   /* Clear all properties.  */
142                   elf_properties (abfd) = NULL;
143                   return FALSE;
144                 }
145               prop = _bfd_elf_get_property (abfd, type, datasz);
146               if (datasz == 8)
147                 prop->u.number = bfd_h_get_64 (abfd, ptr);
148               else
149                 prop->u.number = bfd_h_get_32 (abfd, ptr);
150               prop->pr_kind = property_number;
151               goto next;
152
153             case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
154               if (datasz != 0)
155                 {
156                   _bfd_error_handler
157                     (_("warning: %B: corrupt no copy on protected size: 0x%x\n"),
158                      abfd, datasz);
159                   /* Clear all properties.  */
160                   elf_properties (abfd) = NULL;
161                   return FALSE;
162                 }
163               prop = _bfd_elf_get_property (abfd, type, datasz);
164               prop->pr_kind = property_number;
165               goto next;
166
167             case GNU_PROPERTY_COMPILER_FLAGS:
168               /* Note that annobin uses 4-byte alignment even on 64-bit targets. */
169               if (!((datasz == 4) || (datasz == 8)))
170                 {
171                   _bfd_error_handler
172                     (_("warning: %B: corrupt compiler flags: 0x%x\n"),
173                      abfd, datasz);
174                   /* Clear all properties.  */
175                   elf_properties (abfd) = NULL;
176                   return FALSE;
177                 }
178               prop = _bfd_elf_get_property (abfd, type, datasz);
179               if (datasz == 8)
180                 prop->u.number = bfd_h_get_64 (abfd, ptr);
181               else
182                 prop->u.number = bfd_h_get_32 (abfd, ptr);
183
184               prop->pr_kind = property_number;
185               goto next;
186
187             default:
188               break;
189             }
190         }
191
192       _bfd_error_handler
193         (_("warning: %B: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x\n"),
194          abfd, note->type, type);
195
196 next:
197       ptr += (datasz + (align_size - 1)) & ~ (align_size - 1);
198       if (ptr == ptr_end)
199         break;
200
201       if (ptr > (ptr_end - 8))
202         goto bad_size;
203     }
204
205   return TRUE;
206 }
207
208 /*  If validation bits are set - compare bit flags for equality.  */
209 inline static bfd_boolean
210 elf_gnu_property_validate_flag (bfd_vma anum,
211                                 bfd_vma bnum,
212                                 bfd_vma validation_bit_flag,
213                                 bfd_vma validation_bit)
214 {
215   if ((anum & validation_bit_flag) && (bnum & validation_bit_flag)
216       && ((anum & validation_bit) != (bnum & validation_bit)))
217     {
218       return FALSE;
219     }
220   return TRUE;
221 }
222
223 static bfd_boolean
224 elf_validate_compiler_flags_properties (elf_property *aprop,
225                                         elf_property *bprop)
226 {
227   bfd_boolean is_flag_set;
228
229   /* Sanity check to verify correct usage.  */
230   BFD_ASSERT(aprop);
231   BFD_ASSERT(bprop);
232
233   if (aprop->pr_type != bprop->pr_type)
234     return TRUE;
235
236   BFD_ASSERT(aprop->pr_type == GNU_PROPERTY_COMPILER_FLAGS);
237
238   /* Return TRUE if compiler flags are identical (likely?).  */
239   if (aprop->u.number == bprop->u.number)
240     return TRUE;
241
242   if (!elf_gnu_property_validate_flag(aprop->u.number,
243                                       bprop->u.number,
244                                       GNU_PROPERTY_SANITIZE_VALIDATION,
245                                       GNU_PROPERTY_SANITIZE_ADDRESS))
246     {
247       is_flag_set = bprop->u.number & GNU_PROPERTY_SANITIZE_ADDRESS;
248       _bfd_error_handler
249         (_("%s: ERROR: Validation failed, linking %s object with previous %s"),
250          bprop->filename, is_flag_set ? "sanitized" : "unsanitized",
251          !is_flag_set ? "sanitized" : "unsanitized");
252       return FALSE;
253     }
254
255   if (!elf_gnu_property_validate_flag(aprop->u.number,
256                                       bprop->u.number,
257                                       GNU_PROPERTY_USECXX_VALIDATION,
258                                       GNU_PROPERTY_USECXX11_ABI))
259     {
260       is_flag_set = bprop->u.number & GNU_PROPERTY_USECXX11_ABI;
261       _bfd_error_handler
262         (_("ERROR: Validation failed, linking %s ABI object with %s ABI"),
263          bprop->filename, is_flag_set ? "pre-cxx11" : "cxx11",
264          !is_flag_set ? "pre-cxx11" : "cxx11");
265       return FALSE;
266     }
267
268   return TRUE;
269 }
270
271
272 /* Merge bprop into aprop according compiler-flags properties, return TRUE if */
273 /* aprop is updated. */
274 static bfd_boolean
275 elf_merge_gnu_properties_compiler_flags (elf_property *aprop,
276                                          elf_property *bprop)
277 {
278   bfd_boolean is_updated = FALSE;
279   /* Likely that objects have the same properties.  */
280   if (aprop->u.number == bprop->u.number) {
281     return FALSE;
282   }
283
284   /* Validation bit + no-validation bit = validation bit.  */
285   if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_VALIDATION)
286     {
287       aprop->u.number |= GNU_PROPERTY_SANITIZE_VALIDATION;
288       is_updated = TRUE;
289     }
290   /* Sanitized object + unsanitized results = sanitized final object.  */
291   if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_ADDRESS)
292     {
293       aprop->u.number |= GNU_PROPERTY_SANITIZE_ADDRESS;
294       is_updated = TRUE;
295     }
296
297   if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX_VALIDATION)
298     {
299       aprop->u.number |= GNU_PROPERTY_USECXX_VALIDATION;
300       is_updated = TRUE;
301     }
302
303   if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX11_ABI)
304     {
305       aprop->u.number |= GNU_PROPERTY_USECXX11_ABI;
306       is_updated = TRUE;
307     }
308
309   return is_updated;
310 }
311
312 /* Merge GNU property BPROP with APROP.  If APROP isn't NULL, return TRUE
313    if APROP is updated.  Otherwise, return TRUE if BPROP should be merged
314    with ABFD.  */
315
316 static bfd_boolean
317 elf_merge_gnu_properties (bfd *abfd, elf_property *aprop,
318                           elf_property *bprop)
319 {
320   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
321   unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
322
323   if (bed->merge_gnu_properties != NULL
324       && pr_type >= GNU_PROPERTY_LOPROC
325       && pr_type < GNU_PROPERTY_LOUSER)
326     return bed->merge_gnu_properties (abfd, aprop, bprop);
327
328   switch (pr_type)
329     {
330     case GNU_PROPERTY_STACK_SIZE:
331       if (aprop != NULL && bprop != NULL)
332         {
333           if (bprop->u.number > aprop->u.number)
334             {
335               aprop->u.number = bprop->u.number;
336               return TRUE;
337             }
338           break;
339         }
340       /* FALLTHROUGH */
341
342     case GNU_PROPERTY_NO_COPY_ON_PROTECTED:
343       /* Return TRUE if APROP is NULL to indicate that BPROP should
344          be added to ABFD.  */
345       return aprop == NULL;
346       /* FALLTHROUGH */
347
348     case GNU_PROPERTY_COMPILER_FLAGS:
349       {
350         bfd_boolean is_updated;
351         if (aprop != NULL && bprop != NULL)
352           {
353 #ifdef ENABLE_ANNOBIN_VERIFICATION
354             if (!elf_validate_compiler_flags_properties (aprop, bprop))
355               {
356                 _bfd_error_handler(_("ERROR: Linking failed due to incompatible "
357                                      "compilation flags used to generate objects\n"));
358                 /* Strict mode, abort.  */
359 #ifdef ENABLE_ANNOBIN_VERIFICATION_STRICT
360                 _exit (EXIT_FAILURE);
361 #endif
362               }
363 #endif
364             is_updated = elf_merge_gnu_properties_compiler_flags (aprop, bprop);
365           }
366         else
367           {
368             is_updated = FALSE;
369             /* aprop or bprop is NULL, warn for missing GNU_PROPERTY_COMPILER_FLAGS.
370
371                This is too noisy since glibc's crt{i,n}.o are compiled with
372                predefined flags (without annobin support), so we'll have at
373                least 2x of the following warning for every linking. May be
374                enabled after we verified crt* compilation with plugins.  */
375           /*  if (bprop == NULL)
376               _bfd_error_handler
377                 (_("WARNING: not found (generated by annobin gcc plugin), "
378                    "runtime verification may be incomplete"),
379                  NOTE_GNU_PROPERTY_SECTION_NAME);  */
380           }
381         return is_updated;
382       }
383       /* FALLTHROUGH */
384
385     default:
386       /* Never should happen.  */
387       abort ();
388     }
389
390   return FALSE;
391 }
392
393 /* Return the property of TYPE on *LISTP and remove it from *LISTP.
394    Return NULL if not found.  */
395
396 static elf_property *
397 elf_find_and_remove_property (elf_property_list **listp,
398                               unsigned int type)
399 {
400   elf_property_list *list;
401
402   for (list = *listp; list; list = list->next)
403     {
404       if (type == list->property.pr_type)
405         {
406           /* Remove this property.  */
407           *listp = list->next;
408           return &list->property;
409         }
410       else if (type < list->property.pr_type)
411         break;
412       listp = &list->next;
413     }
414
415   return NULL;
416 }
417
418 /* Merge GNU property list *LISTP with ABFD.  */
419
420 static void
421 elf_merge_gnu_property_list (bfd *abfd, elf_property_list **listp)
422 {
423   elf_property_list *p, **lastp;
424   elf_property *pr;
425
426   /* Merge each GNU property in ABFD with the one on *LISTP.  */
427   lastp = &elf_properties (abfd);
428   for (p = *lastp; p; p = p->next)
429     {
430       pr = elf_find_and_remove_property (listp, p->property.pr_type);
431       /* Pass NULL to elf_merge_gnu_properties for the property which
432          isn't on *LISTP.  */
433       elf_merge_gnu_properties (abfd, &p->property, pr);
434       if (p->property.pr_kind == property_remove)
435         {
436           /* Remove this property.  */
437           *lastp = p->next;
438           continue;
439         }
440       lastp = &p->next;
441     }
442
443   /* Merge the remaining properties on *LISTP with ABFD.  */
444   for (p = *listp; p != NULL; p = p->next)
445     if (elf_merge_gnu_properties (abfd, NULL, &p->property))
446       {
447         pr = _bfd_elf_get_property (abfd, p->property.pr_type,
448                                     p->property.pr_datasz);
449         /* It must be a new property.  */
450         if (pr->pr_kind != property_unknown)
451           abort ();
452         /* Add a new property.  */
453         *pr = p->property;
454       }
455 }
456
457 /* Set up GNU properties.  */
458
459 void
460 _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
461 {
462   bfd *abfd, *first_pbfd = NULL;
463   elf_property_list *list;
464   asection *sec;
465   bfd_boolean has_properties = FALSE;
466   const struct elf_backend_data *bed
467     = get_elf_backend_data (info->output_bfd);
468   unsigned int elfclass = bed->s->elfclass;
469   int elf_machine_code = bed->elf_machine_code;
470
471   /* Find the first relocatable ELF input with GNU properties.  */
472   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
473     if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
474         && bfd_count_sections (abfd) != 0
475         && elf_properties (abfd) != NULL)
476       {
477         has_properties = TRUE;
478
479         /* Ignore GNU properties from ELF objects with different machine
480            code or class.  */
481         if ((elf_machine_code
482              == get_elf_backend_data (abfd)->elf_machine_code)
483             && (elfclass
484                 == get_elf_backend_data (abfd)->s->elfclass))
485           {
486             /* Keep .note.gnu.property section in FIRST_PBFD.  */
487             first_pbfd = abfd;
488             break;
489           }
490       }
491
492   /* Do nothing if there is no .note.gnu.property section.  */
493   if (!has_properties)
494     return;
495
496   /* Merge .note.gnu.property sections.  */
497   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
498     if (abfd != first_pbfd && bfd_count_sections (abfd) != 0)
499       {
500         elf_property_list *null_ptr = NULL;
501         elf_property_list **listp = &null_ptr;
502
503         /* Merge .note.gnu.property section in relocatable ELF input.  */
504         if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
505           {
506             list = elf_properties (abfd);
507
508             /* Ignore GNU properties from ELF objects with different
509                machine code.  */
510             if (list != NULL
511                 && (elf_machine_code
512                     == get_elf_backend_data (abfd)->elf_machine_code))
513               listp = &elf_properties (abfd);
514           }
515         else
516           list = NULL;
517
518         /* Merge properties with FIRST_PBFD.  FIRST_PBFD can be NULL
519            when all properties are from ELF objects with different
520            machine code or class.  */
521         if (first_pbfd != NULL)
522           elf_merge_gnu_property_list (first_pbfd, listp);
523
524         if (list != NULL)
525           {
526             /* Discard .note.gnu.property section in the rest inputs.  */
527             sec = bfd_get_section_by_name (abfd,
528                                            NOTE_GNU_PROPERTY_SECTION_NAME);
529             sec->output_section = bfd_abs_section_ptr;
530           }
531       }
532
533   /* Rewrite .note.gnu.property section so that GNU properties are
534      always sorted by type even if input GNU properties aren't sorted.  */
535   if (first_pbfd != NULL)
536     {
537       unsigned int size;
538       unsigned int descsz;
539       bfd_byte *contents;
540       Elf_External_Note *e_note;
541       unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
542
543       sec = bfd_get_section_by_name (first_pbfd,
544                                      NOTE_GNU_PROPERTY_SECTION_NAME);
545
546       if (!sec)
547         return;
548
549       /* Update stack size in .note.gnu.property with -z stack-size=N
550          if N > 0.  */
551       if (info->stacksize > 0)
552         {
553           elf_property *p;
554           bfd_vma stacksize = info->stacksize;
555
556           p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_STACK_SIZE,
557                                      align_size);
558           if (p->pr_kind == property_unknown)
559             {
560               /* Create GNU_PROPERTY_STACK_SIZE.  */
561               p->u.number = stacksize;
562               p->pr_kind = property_number;
563             }
564           else if (stacksize > p->u.number)
565             p->u.number = stacksize;
566         }
567       else if (elf_properties (first_pbfd) == NULL)
568         {
569           /* Discard .note.gnu.property section if all properties have
570              been removed.  */
571           sec->output_section = bfd_abs_section_ptr;
572           return;
573         }
574
575       /* Compute the section size.  */
576       descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
577       descsz = (descsz + 3) & -(unsigned int) 4;
578       size = descsz;
579       for (list = elf_properties (first_pbfd);
580            list != NULL;
581            list = list->next)
582         {
583           /* There are 4 byte type + 4 byte datasz for each property.  */
584           size += 4 + 4 + list->property.pr_datasz;
585           /* Align each property.  */
586           size = (size + (align_size - 1)) & ~(align_size - 1);
587         }
588
589       /* Update .note.gnu.property section now.  */
590       sec->size = size;
591       contents = (bfd_byte *) bfd_zalloc (first_pbfd, size);
592
593       e_note = (Elf_External_Note *) contents;
594       bfd_h_put_32 (first_pbfd, sizeof "GNU", &e_note->namesz);
595       bfd_h_put_32 (first_pbfd, size - descsz, &e_note->descsz);
596       bfd_h_put_32 (first_pbfd, NT_GNU_PROPERTY_TYPE_0, &e_note->type);
597       memcpy (e_note->name, "GNU", sizeof "GNU");
598
599       size = descsz;
600       for (list = elf_properties (first_pbfd);
601            list != NULL;
602            list = list->next)
603         {
604           /* There are 4 byte type + 4 byte datasz for each property.  */
605           bfd_h_put_32 (first_pbfd, list->property.pr_type,
606                         contents + size);
607           bfd_h_put_32 (first_pbfd, list->property.pr_datasz,
608                         contents + size + 4);
609           size += 4 + 4;
610
611           /* Write out property value.  */
612           switch (list->property.pr_kind)
613             {
614             case property_number:
615               switch (list->property.pr_datasz)
616                 {
617                 default:
618                   /* Never should happen.  */
619                   abort ();
620
621                 case 0:
622                   break;
623
624                 case 4:
625                   bfd_h_put_32 (first_pbfd, list->property.u.number,
626                                 contents + size);
627                   break;
628
629                 case 8:
630                   bfd_h_put_64 (first_pbfd, list->property.u.number,
631                                 contents + size);
632                   break;
633                 }
634               break;
635
636             default:
637               /* Never should happen.  */
638               abort ();
639             }
640           size += list->property.pr_datasz;
641
642           /* Align each property.  */
643           size = (size + (align_size - 1)) & ~ (align_size - 1);
644         }
645
646       /* Cache the section contents for elf_link_input_bfd.  */
647       elf_section_data (sec)->this_hdr.contents = contents;
648     }
649 }