Check multiple NT_GNU_PROPERTY_TYPE_0 notes [BZ #23509]
Commit Message
The older linker treats .note.gnu.property section as a generic note
section and just concatenates all .note.gnu.property sections from the
inputs to the output. When the older linker is used to created the
program on CET-enabled OS, the generated output has .note.gnu.property
section with multiple NT_GNU_PROPERTY_TYPE_0 notes whose IBT and SHSTK
enable bits are set even if the program isn't CET enabled. Such program
will crash on CET-enabled machines. This patch updates the note parser:
1. Skip note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
2. Check multiple NT_GNU_PROPERTY_TYPE_0 notes.
OK for master?
H.J.
---
[BZ #23509]
* sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Skip
note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed.
Update the l_cet field when processing NT_GNU_PROPERTY_TYPE_0 note.
Check multiple NT_GNU_PROPERTY_TYPE_0 notes.
* sysdeps/x86/link_map.h (l_cet): Expand to 3 bits, Add
lc_unknown.
---
sysdeps/x86/dl-prop.h | 51 +++++++++++++++++++++++++++++++++---------
sysdeps/x86/link_map.h | 9 ++++----
2 files changed, 46 insertions(+), 14 deletions(-)
Comments
On 08/14/2018 07:32 PM, H.J. Lu wrote:
> #if CET_ENABLED
> + /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
> + if (l->l_cet != lc_unknown)
> + return;
Should this set l->l_cet to lc_none before returning?
> + /* Stop if we see more than one GNU property note which may
> + be generated by the older linker. */
> + if (l->l_cet != lc_unknown)
> + return;
Likewise.
Thanks,
Florian
On Tue, Aug 14, 2018 at 10:59 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/14/2018 07:32 PM, H.J. Lu wrote:
>
>> #if CET_ENABLED
>> + /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
>> + if (l->l_cet != lc_unknown)
>> + return;
>
>
> Should this set l->l_cet to lc_none before returning?
>
>> + /* Stop if we see more than one GNU property note which may
>> + be generated by the older linker. */
>> + if (l->l_cet != lc_unknown)
>> + return;
>
>
> Likewise.
>
_dl_process_cet_property_note is called on on each PT_NOTE segment.
We must keep searching until we found a PT_NOTE segment with a
NT_GNU_PROPERTY_TYPE_0 note:
/* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
if (l->l_cet != lc_unknown)
return;
...
<<< Found a PT_NOTE segment, which may not contain
the NT_GNU_PROPERTY_TYPE_0 note.
/* Find the NT_GNU_PROPERTY_TYPE_0 note. */
if (note->n_namesz == 4
&& note->n_type == NT_GNU_PROPERTY_TYPE_0
&& memcmp (note + 1, "GNU", 4) == 0)
{
<<< Now we found a NT_GNU_PROPERTY_TYPE_0 note.
/* Stop if we see more than one GNU property note which may
be generated by the older linker. */
if (l->l_cet != lc_unknown) <<<<<<< l_cet starts with lc_unknown.
return;
/* Check CET status now. */
l->l_cet = lc_none; <<<<<<<<< Set l_cet to lc_none now.
l->l_cet may be left as lc_unknown if there is no NT_GNU_PROPERTY_TYPE_0
note.
On 08/14/2018 08:12 PM, H.J. Lu wrote:
> _dl_process_cet_property_note is called on on each PT_NOTE segment.
> We must keep searching until we found a PT_NOTE segment with a
> NT_GNU_PROPERTY_TYPE_0 note:
>
> /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
> if (l->l_cet != lc_unknown)
> return;
> ...
What if there are different segments, each one with its own
NT_GNU_PROPERTY_TYPE_0? Wouldn't that point to lack of linker support,
too? So that CET needs to be disabled?
Thanks,
Florian
On Wed, Aug 15, 2018 at 8:17 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/14/2018 08:12 PM, H.J. Lu wrote:
>>
>> _dl_process_cet_property_note is called on on each PT_NOTE segment.
>> We must keep searching until we found a PT_NOTE segment with a
>> NT_GNU_PROPERTY_TYPE_0 note:
>>
>> /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
>> if (l->l_cet != lc_unknown)
>> return;
>> ...
>
>
> What if there are different segments, each one with its own
> NT_GNU_PROPERTY_TYPE_0? Wouldn't that point to lack of linker support, too?
> So that CET needs to be disabled?
Older linkers puts all NT_GNU_PROPERTY_TYPE_0 notes in one
.note.gnu.property section. One can certainly create some random notes
which look like NT_GNU_PROPERTY_TYPE_0. I don't think we need to
check these notes.
On 08/15/2018 05:23 PM, H.J. Lu wrote:
> On Wed, Aug 15, 2018 at 8:17 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 08/14/2018 08:12 PM, H.J. Lu wrote:
>>>
>>> _dl_process_cet_property_note is called on on each PT_NOTE segment.
>>> We must keep searching until we found a PT_NOTE segment with a
>>> NT_GNU_PROPERTY_TYPE_0 note:
>>>
>>> /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
>>> if (l->l_cet != lc_unknown)
>>> return;
>>> ...
>>
>>
>> What if there are different segments, each one with its own
>> NT_GNU_PROPERTY_TYPE_0? Wouldn't that point to lack of linker support, too?
>> So that CET needs to be disabled?
>
> Older linkers puts all NT_GNU_PROPERTY_TYPE_0 notes in one
> .note.gnu.property section. One can certainly create some random notes
> which look like NT_GNU_PROPERTY_TYPE_0. I don't think we need to
> check these notes.
I think older BFD ld creates multiple segments.
Thanks,
Florian
On Wed, Aug 15, 2018 at 8:25 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/15/2018 05:23 PM, H.J. Lu wrote:
>>
>> On Wed, Aug 15, 2018 at 8:17 AM, Florian Weimer <fweimer@redhat.com>
>> wrote:
>>>
>>> On 08/14/2018 08:12 PM, H.J. Lu wrote:
>>>>
>>>>
>>>> _dl_process_cet_property_note is called on on each PT_NOTE segment.
>>>> We must keep searching until we found a PT_NOTE segment with a
>>>> NT_GNU_PROPERTY_TYPE_0 note:
>>>>
>>>> /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
>>>> if (l->l_cet != lc_unknown)
>>>> return;
>>>> ...
>>>
>>>
>>>
>>> What if there are different segments, each one with its own
>>> NT_GNU_PROPERTY_TYPE_0? Wouldn't that point to lack of linker support,
>>> too?
>>> So that CET needs to be disabled?
>>
>>
>> Older linkers puts all NT_GNU_PROPERTY_TYPE_0 notes in one
>> .note.gnu.property section. One can certainly create some random notes
>> which look like NT_GNU_PROPERTY_TYPE_0. I don't think we need to
>> check these notes.
>
>
> I think older BFD ld creates multiple segments.
Which version of ld dos that?
On 08/15/2018 05:29 PM, H.J. Lu wrote:
> On Wed, Aug 15, 2018 at 8:25 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 08/15/2018 05:23 PM, H.J. Lu wrote:
>>>
>>> On Wed, Aug 15, 2018 at 8:17 AM, Florian Weimer <fweimer@redhat.com>
>>> wrote:
>>>>
>>>> On 08/14/2018 08:12 PM, H.J. Lu wrote:
>>>>>
>>>>>
>>>>> _dl_process_cet_property_note is called on on each PT_NOTE segment.
>>>>> We must keep searching until we found a PT_NOTE segment with a
>>>>> NT_GNU_PROPERTY_TYPE_0 note:
>>>>>
>>>>> /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
>>>>> if (l->l_cet != lc_unknown)
>>>>> return;
>>>>> ...
>>>>
>>>>
>>>>
>>>> What if there are different segments, each one with its own
>>>> NT_GNU_PROPERTY_TYPE_0? Wouldn't that point to lack of linker support,
>>>> too?
>>>> So that CET needs to be disabled?
>>>
>>>
>>> Older linkers puts all NT_GNU_PROPERTY_TYPE_0 notes in one
>>> .note.gnu.property section. One can certainly create some random notes
>>> which look like NT_GNU_PROPERTY_TYPE_0. I don't think we need to
>>> check these notes.
>>
>>
>> I think older BFD ld creates multiple segments.
>
> Which version of ld dos that?
Examples that got me worried look like this:
$ readelf -l /usr/bin/b5i2iso
…
NOTE 0x0000000000000334 0x0000000000400334 0x0000000000400334
0x0000000000000020 0x0000000000000020 R 0x4
NOTE 0x0000000000000358 0x0000000000400358 0x0000000000400358
0x0000000000000030 0x0000000000000030 R 0x8
NOTE 0x0000000000000388 0x0000000000400388 0x0000000000400388
0x0000000000000024 0x0000000000000024 R 0x4
…
07 .note.ABI-tag
08 .note.gnu.property
09 .note.gnu.build-id
…
$ rpm -qf /usr/bin/b5i2iso
AcetoneISO-6.7-26.fc29.x86_64
Per
<https://kojipkgs.fedoraproject.org//packages/AcetoneISO/6.7/26.fc29/data/logs/x86_64/root.log>,
this was built with binutils-2.30.90-4.fc29.
I don't know enough about the binutils linker to be certain that
allocatable SHT_NOTE sections of the same name always go into the same
PT_NOTE segment. In the example above, the sections weren't split.
Thanks,
Florian
On Thu, Aug 16, 2018 at 4:28 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/15/2018 05:29 PM, H.J. Lu wrote:
>>
>> On Wed, Aug 15, 2018 at 8:25 AM, Florian Weimer <fweimer@redhat.com>
>> wrote:
>>>
>>> On 08/15/2018 05:23 PM, H.J. Lu wrote:
>>>>
>>>>
>>>> On Wed, Aug 15, 2018 at 8:17 AM, Florian Weimer <fweimer@redhat.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 08/14/2018 08:12 PM, H.J. Lu wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> _dl_process_cet_property_note is called on on each PT_NOTE segment.
>>>>>> We must keep searching until we found a PT_NOTE segment with a
>>>>>> NT_GNU_PROPERTY_TYPE_0 note:
>>>>>>
>>>>>> /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
>>>>>> if (l->l_cet != lc_unknown)
>>>>>> return;
>>>>>> ...
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> What if there are different segments, each one with its own
>>>>> NT_GNU_PROPERTY_TYPE_0? Wouldn't that point to lack of linker support,
>>>>> too?
>>>>> So that CET needs to be disabled?
>>>>
>>>>
>>>>
>>>> Older linkers puts all NT_GNU_PROPERTY_TYPE_0 notes in one
>>>> .note.gnu.property section. One can certainly create some random notes
>>>> which look like NT_GNU_PROPERTY_TYPE_0. I don't think we need to
>>>> check these notes.
>>>
>>>
>>>
>>> I think older BFD ld creates multiple segments.
>>
>>
>> Which version of ld dos that?
>
>
> Examples that got me worried look like this:
>
> $ readelf -l /usr/bin/b5i2iso
> …
> NOTE 0x0000000000000334 0x0000000000400334 0x0000000000400334
> 0x0000000000000020 0x0000000000000020 R 0x4
> NOTE 0x0000000000000358 0x0000000000400358 0x0000000000400358
> 0x0000000000000030 0x0000000000000030 R 0x8
> NOTE 0x0000000000000388 0x0000000000400388 0x0000000000400388
> 0x0000000000000024 0x0000000000000024 R 0x4
> …
> 07 .note.ABI-tag
> 08 .note.gnu.property
> 09 .note.gnu.build-id
> …
> $ rpm -qf /usr/bin/b5i2iso
> AcetoneISO-6.7-26.fc29.x86_64
>
> Per
> <https://kojipkgs.fedoraproject.org//packages/AcetoneISO/6.7/26.fc29/data/logs/x86_64/root.log>,
> this was built with binutils-2.30.90-4.fc29.
>
> I don't know enough about the binutils linker to be certain that allocatable
> SHT_NOTE sections of the same name always go into the same PT_NOTE segment.
> In the example above, the sections weren't split.
Please show the output of "readelf -n". I believe that all
NT_GNU_PROPERTY_TYPE_0
notes are in a single PT_NOTE segment. My patch checks each PT_LOAD segment
until a NT_GNU_PROPERTY_TYPE_0 note is found. If more than one note is found,
it disables CET since the binary was created by the older linker.
BTW, the new linker also creates more than one note:
[hjl@gnu-cfl-1 binutils]$ readelf -ln /bin/sprof
Elf file type is DYN (Shared object file)
Entry point 0x36d0
There are 12 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000002a0 0x00000000000002a0 R 0x8
INTERP 0x00000000000002e0 0x00000000000002e0 0x00000000000002e0
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000001708 0x0000000000001708 R 0x1000
LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000
0x0000000000002fc5 0x0000000000002fc5 R E 0x1000
LOAD 0x0000000000005000 0x0000000000005000 0x0000000000005000
0x0000000000000c30 0x0000000000000c30 R 0x1000
LOAD 0x0000000000005c70 0x0000000000006c70 0x0000000000006c70
0x0000000000000590 0x0000000000000670 RW 0x1000
DYNAMIC 0x0000000000005dc8 0x0000000000006dc8 0x0000000000006dc8
0x0000000000000200 0x0000000000000200 RW 0x8
NOTE 0x0000000000000300 0x0000000000000300 0x0000000000000300
0x0000000000000020 0x0000000000000020 R 0x8
NOTE 0x0000000000000320 0x0000000000000320 0x0000000000000320
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x00000000000058f0 0x00000000000058f0 0x00000000000058f0
0x00000000000000ac 0x00000000000000ac R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000005c70 0x0000000000006c70 0x0000000000006c70
0x0000000000000390 0x0000000000000390 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.property .note.ABI-tag .note.gnu.build-id
.hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn
.rela.plt
03 .init .plt .plt.got .plt.sec .text .fini
04 .rodata .eh_frame_hdr .eh_frame
05 .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .bss
06 .dynamic
07 .note.gnu.property
08 .note.ABI-tag .note.gnu.build-id
09 .eh_frame_hdr
10
11 .init_array .fini_array .data.rel.ro .dynamic .got
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: x86 feature: IBT, SHSTK
Displaying notes found in: .note.ABI-tag
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 3.2.0
Displaying notes found in: .note.gnu.build-id
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 59cb797230842a68fe5d61189f03c50acb9e84bf
[hjl@gnu-cfl-1 binutils]$
On 08/16/2018 01:39 PM, H.J. Lu wrote:
> Please show the output of "readelf -n". I believe that all
> NT_GNU_PROPERTY_TYPE_0
> notes are in a single PT_NOTE segment.
There is just one property note because the linker has property note
merging support:
Displaying notes found in: .note.ABI-tag
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 3.2.0
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA used:
x86 ISA needed:
Displaying notes found in: .note.gnu.build-id
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build
ID bitstring)
Build ID: 5bd43ed7376c4734e49138a6bddb15dc0d0002a6
> My patch checks each PT_LOAD segment
> until a NT_GNU_PROPERTY_TYPE_0 note is found. If more than one note is found,
> it disables CET since the binary was created by the older linker.
I assumed the patch stopped searching once it finds a segment with a
single NT_GNU_PROPERTY_TYPE_0 note. I'm still worried that this might
be a problem, considering that ld produces multiple segments in some
cases (but the triggering conditions for that aren't entirely clear to me).
Thanks,
Florian
On Thu, Aug 16, 2018 at 4:47 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/16/2018 01:39 PM, H.J. Lu wrote:
>
>> Please show the output of "readelf -n". I believe that all
>> NT_GNU_PROPERTY_TYPE_0
>> notes are in a single PT_NOTE segment.
>
>
> There is just one property note because the linker has property note merging
> support:
>
> Displaying notes found in: .note.ABI-tag
> Owner Data size Description
> GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
> OS: Linux, ABI: 3.2.0
>
> Displaying notes found in: .note.gnu.property
> Owner Data size Description
> GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
> Properties: x86 ISA used:
> x86 ISA needed:
>
> Displaying notes found in: .note.gnu.build-id
> Owner Data size Description
> GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID
> bitstring)
> Build ID: 5bd43ed7376c4734e49138a6bddb15dc0d0002a6
>
>> My patch checks each PT_LOAD segment
>> until a NT_GNU_PROPERTY_TYPE_0 note is found. If more than one note is
>> found,
>> it disables CET since the binary was created by the older linker.
>
>
> I assumed the patch stopped searching once it finds a segment with a single
> NT_GNU_PROPERTY_TYPE_0 note. I'm still worried that this might be a
> problem, considering that ld produces multiple segments in some cases (but
> the triggering conditions for that aren't entirely clear to me).
>
Multiple segments are perfectly normal. But there is only one
.note.gnu.property
section, which may contain more then one NT_GNU_PROPERTY_TYPE_0 notes.
This was built by the old linker:
[hjl@gnu-cet-1 pr23509]$ readelf -n foo
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature: IBT, SHSTK
Invalid x86 feature used: x86
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature: IBT, SHSTK
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature used: x86
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature: IBT, SHSTK
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature used: x86
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature: IBT, SHSTK
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature used: x86
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature: IBT, SHSTK
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature: IBT, SHSTK
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: Invalid x86 feature used: x86
Displaying notes found in: .note.ABI-tag
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 3.2.0
Displaying notes found in: .note.gnu.build-id
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: e07c4ee5b30388bc95738a19cba8b9e13018176c
[hjl@gnu-cet-1 pr23509]$
On 08/16/2018 02:10 PM, H.J. Lu wrote:
> Multiple segments are perfectly normal.
I'm not convinced that they are desirable. They really should be merged.
> But there is only one
> .note.gnu.property
> section, which may contain more then one NT_GNU_PROPERTY_TYPE_0 notes.
My worry is that if the linker generates multiple note segments, it
might as well produce multiple segments from the .note.gnu.property section.
Florian
On Thu, Aug 16, 2018 at 5:29 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/16/2018 02:10 PM, H.J. Lu wrote:
>
>> Multiple segments are perfectly normal.
>
>
> I'm not convinced that they are desirable. They really should be merged.
They aren't merged since they have different alignments.
>> But there is only one
>> .note.gnu.property
>> section, which may contain more then one NT_GNU_PROPERTY_TYPE_0 notes.
>
>
> My worry is that if the linker generates multiple note segments, it might as
> well produce multiple segments from the .note.gnu.property section.
Linker generates multiple segments because of different segment alignments.
But linker should always place all .note.gnu.property sections from inputs in
one output .note.gnu.property section. You can try different older linkers.
They should all behave the same.
@@ -49,6 +49,10 @@ _dl_process_cet_property_note (struct link_map *l,
const ElfW(Addr) align)
{
#if CET_ENABLED
+ /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */
+ if (l->l_cet != lc_unknown)
+ return;
+
/* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in
32-bit objects and to 8 bytes in 64-bit objects. Skip notes
with incorrect alignment. */
@@ -57,6 +61,9 @@ _dl_process_cet_property_note (struct link_map *l,
const ElfW(Addr) start = (ElfW(Addr)) note;
+ unsigned int feature_1 = 0;
+ unsigned int last_type = 0;
+
while ((ElfW(Addr)) (note + 1) - start < size)
{
/* Find the NT_GNU_PROPERTY_TYPE_0 note. */
@@ -64,10 +71,18 @@ _dl_process_cet_property_note (struct link_map *l,
&& note->n_type == NT_GNU_PROPERTY_TYPE_0
&& memcmp (note + 1, "GNU", 4) == 0)
{
+ /* Stop if we see more than one GNU property note which may
+ be generated by the older linker. */
+ if (l->l_cet != lc_unknown)
+ return;
+
+ /* Check CET status now. */
+ l->l_cet = lc_none;
+
/* Check for invalid property. */
if (note->n_descsz < 8
|| (note->n_descsz % sizeof (ElfW(Addr))) != 0)
- break;
+ return;
/* Start and end of property array. */
unsigned char *ptr = (unsigned char *) (note + 1) + 4;
@@ -78,9 +93,15 @@ _dl_process_cet_property_note (struct link_map *l,
unsigned int type = *(unsigned int *) ptr;
unsigned int datasz = *(unsigned int *) (ptr + 4);
+ /* Property type must be in ascending order. */
+ if (type <= last_type)
+ return;
+
ptr += 8;
if ((ptr + datasz) > ptr_end)
- break;
+ return;
+
+ last_type = type;
if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
{
@@ -89,14 +110,18 @@ _dl_process_cet_property_note (struct link_map *l,
we stop the search regardless if its size is correct
or not. There is no point to continue if this note
is ill-formed. */
- if (datasz == 4)
- {
- unsigned int feature_1 = *(unsigned int *) ptr;
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
- l->l_cet |= lc_ibt;
- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
- l->l_cet |= lc_shstk;
- }
+ if (datasz != 4)
+ return;
+
+ feature_1 = *(unsigned int *) ptr;
+
+ /* Keep searching for the next GNU property note
+ generated by the older linker. */
+ break;
+ }
+ else if (type > GNU_PROPERTY_X86_FEATURE_1_AND)
+ {
+ /* Stop since property type is in ascending order. */
return;
}
@@ -112,6 +137,12 @@ _dl_process_cet_property_note (struct link_map *l,
+ ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz,
align));
}
+
+ /* We get here only if there is one or no GNU property note. */
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT))
+ l->l_cet |= lc_ibt;
+ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
+ l->l_cet |= lc_shstk;
#endif
}
@@ -19,8 +19,9 @@
/* If this object is enabled with CET. */
enum
{
- lc_none = 0, /* Not enabled with CET. */
- lc_ibt = 1 << 0, /* Enabled with IBT. */
- lc_shstk = 1 << 1, /* Enabled with STSHK. */
+ lc_unknown = 0, /* Unknown CET status. */
+ lc_none = 1 << 0, /* Not enabled with CET. */
+ lc_ibt = 1 << 1, /* Enabled with IBT. */
+ lc_shstk = 1 << 2, /* Enabled with STSHK. */
lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both. */
- } l_cet:2;
+ } l_cet:3;