2017-08-09 17:07:58

by Kees Cook

[permalink] [raw]
Subject: new ELF marking

Hi,

I'd like to be able to mark an ELF binary in such a way that Linux's
binfmt_elf.c will collapse a PIE text area into the mmap region
(currently they are separately randomized in memory). This is desired
by AddressSanitizer to avoid having an ASan-built binary have its text
area moving into an unexpected location[1] (ASLR is still desired, but
doesn't need to have a PIE/mmap split).

I see a few ways:

- Add parsing for NOTE program headers and add a new NOTE type
(NT_GNU_EXEC_FLAGS), though notes tend to be strings...

- Add a new Program Header (GNU_EXEC_FLAGS), which is similar to how
GNU_STACK and GNU_RELRO were handled. This could sort of be like NOTE
except just lots of bit flags.

- Use a filesystem xattr. This is fragile, in the case of copying
binaries between systems or filesystems.

Thoughts?

-Kees

[1] https://lkml.org/lkml/2017/8/7/770

--
Kees Cook
Pixel Security


2017-08-09 17:17:02

by H.J. Lu

[permalink] [raw]
Subject: Re: new ELF marking

On Wed, Aug 9, 2017 at 10:07 AM, Kees Cook via binutils
<[email protected]> wrote:
> Hi,
>
> I'd like to be able to mark an ELF binary in such a way that Linux's
> binfmt_elf.c will collapse a PIE text area into the mmap region
> (currently they are separately randomized in memory). This is desired
> by AddressSanitizer to avoid having an ASan-built binary have its text
> area moving into an unexpected location[1] (ASLR is still desired, but
> doesn't need to have a PIE/mmap split).
>
> I see a few ways:
>
> - Add parsing for NOTE program headers and add a new NOTE type
> (NT_GNU_EXEC_FLAGS), though notes tend to be strings...
>
> - Add a new Program Header (GNU_EXEC_FLAGS), which is similar to how
> GNU_STACK and GNU_RELRO were handled. This could sort of be like NOTE
> except just lots of bit flags.
>
> - Use a filesystem xattr. This is fragile, in the case of copying
> binaries between systems or filesystems.
>
> Thoughts?
>
>

Why don't you use NT_GNU_PROPERTY_TYPE_0?

--
H.J.

2017-08-09 18:26:13

by Kees Cook

[permalink] [raw]
Subject: Re: new ELF marking

On Wed, Aug 9, 2017 at 10:16 AM, H.J. Lu <[email protected]> wrote:
> On Wed, Aug 9, 2017 at 10:07 AM, Kees Cook via binutils
> <[email protected]> wrote:
>> Hi,
>>
>> I'd like to be able to mark an ELF binary in such a way that Linux's
>> binfmt_elf.c will collapse a PIE text area into the mmap region
>> (currently they are separately randomized in memory). This is desired
>> by AddressSanitizer to avoid having an ASan-built binary have its text
>> area moving into an unexpected location[1] (ASLR is still desired, but
>> doesn't need to have a PIE/mmap split).
>>
>> I see a few ways:
>>
>> - Add parsing for NOTE program headers and add a new NOTE type
>> (NT_GNU_EXEC_FLAGS), though notes tend to be strings...
>>
>> - Add a new Program Header (GNU_EXEC_FLAGS), which is similar to how
>> GNU_STACK and GNU_RELRO were handled. This could sort of be like NOTE
>> except just lots of bit flags.
>>
>> - Use a filesystem xattr. This is fragile, in the case of copying
>> binaries between systems or filesystems.
>>
>> Thoughts?
>>
>>
>
> Why don't you use NT_GNU_PROPERTY_TYPE_0?

Ah, interesting. I hadn't seen this before. Docs I found were:
https://github.com/hjl-tools/linux-abi/commit/a24f6898c4172e09b2e476ae9f160621528a1d92

\item[pr_datasz] The size of the \code{pr_data} field. A 4-byte
integer in the format of the target processor.
\item[pr_data] The program property descriptor. An array of 4-byte
integers in 32-bit object or 8-byte integers in 64-bit objects, in
the format of the target processor.

Is pr_data length always a multiple of 4 (or 8)? I found this language
confusing, given that pr_datasz doesn't mention this.

Also, given the definition, should the kernel examine these, or should
it remain limited to the runtimer loader?

If the kernel should, would it be better to add
GNU_PROPERTY_EXEC_FLAGS, for future bits, or should it be something
like GNU_PROPERTY_NO_COPY_ON_PROTECTED with a pr_datasz == 0?

(And should the kernel already be parsing GNU_PROPERTY_STACK_SIZE?)

-Kees

--
Kees Cook
Pixel Security

2017-08-09 18:46:27

by H.J. Lu

[permalink] [raw]
Subject: Re: new ELF marking

On Wed, Aug 9, 2017 at 11:26 AM, Kees Cook <[email protected]> wrote:
> On Wed, Aug 9, 2017 at 10:16 AM, H.J. Lu <[email protected]> wrote:
>> On Wed, Aug 9, 2017 at 10:07 AM, Kees Cook via binutils
>> <[email protected]> wrote:
>>> Hi,
>>>
>>> I'd like to be able to mark an ELF binary in such a way that Linux's
>>> binfmt_elf.c will collapse a PIE text area into the mmap region
>>> (currently they are separately randomized in memory). This is desired
>>> by AddressSanitizer to avoid having an ASan-built binary have its text
>>> area moving into an unexpected location[1] (ASLR is still desired, but
>>> doesn't need to have a PIE/mmap split).
>>>
>>> I see a few ways:
>>>
>>> - Add parsing for NOTE program headers and add a new NOTE type
>>> (NT_GNU_EXEC_FLAGS), though notes tend to be strings...
>>>
>>> - Add a new Program Header (GNU_EXEC_FLAGS), which is similar to how
>>> GNU_STACK and GNU_RELRO were handled. This could sort of be like NOTE
>>> except just lots of bit flags.
>>>
>>> - Use a filesystem xattr. This is fragile, in the case of copying
>>> binaries between systems or filesystems.
>>>
>>> Thoughts?
>>>
>>>
>>
>> Why don't you use NT_GNU_PROPERTY_TYPE_0?
>
> Ah, interesting. I hadn't seen this before. Docs I found were:
> https://github.com/hjl-tools/linux-abi/commit/a24f6898c4172e09b2e476ae9f160621528a1d92
>
> \item[pr_datasz] The size of the \code{pr_data} field. A 4-byte
> integer in the format of the target processor.
> \item[pr_data] The program property descriptor. An array of 4-byte
> integers in 32-bit object or 8-byte integers in 64-bit objects, in
> the format of the target processor.
>
> Is pr_data length always a multiple of 4 (or 8)? I found this language

Yes.

> confusing, given that pr_datasz doesn't mention this.
>
> Also, given the definition, should the kernel examine these, or should
> it remain limited to the runtimer loader?

Both kernel and run-time loaders should check it. I am working on
static PIE, which is loaded by kernel.

> If the kernel should, would it be better to add
> GNU_PROPERTY_EXEC_FLAGS, for future bits, or should it be something
> like GNU_PROPERTY_NO_COPY_ON_PROTECTED with a pr_datasz == 0?

Please use bits. Is this an output only bit? Will it appear in an input file?

> (And should the kernel already be parsing GNU_PROPERTY_STACK_SIZE?)
>

Kernel should.

--
H.J.

2017-08-09 18:52:10

by Kees Cook

[permalink] [raw]
Subject: Re: new ELF marking

On Wed, Aug 9, 2017 at 11:46 AM, H.J. Lu <[email protected]> wrote:
> On Wed, Aug 9, 2017 at 11:26 AM, Kees Cook <[email protected]> wrote:
>> On Wed, Aug 9, 2017 at 10:16 AM, H.J. Lu <[email protected]> wrote:
>>> On Wed, Aug 9, 2017 at 10:07 AM, Kees Cook via binutils
>>> <[email protected]> wrote:
>>>> Hi,
>>>>
>>>> I'd like to be able to mark an ELF binary in such a way that Linux's
>>>> binfmt_elf.c will collapse a PIE text area into the mmap region
>>>> (currently they are separately randomized in memory). This is desired
>>>> by AddressSanitizer to avoid having an ASan-built binary have its text
>>>> area moving into an unexpected location[1] (ASLR is still desired, but
>>>> doesn't need to have a PIE/mmap split).
>>>>
>>>> I see a few ways:
>>>>
>>>> - Add parsing for NOTE program headers and add a new NOTE type
>>>> (NT_GNU_EXEC_FLAGS), though notes tend to be strings...
>>>>
>>>> - Add a new Program Header (GNU_EXEC_FLAGS), which is similar to how
>>>> GNU_STACK and GNU_RELRO were handled. This could sort of be like NOTE
>>>> except just lots of bit flags.
>>>>
>>>> - Use a filesystem xattr. This is fragile, in the case of copying
>>>> binaries between systems or filesystems.
>>>>
>>>> Thoughts?
>>>>
>>>>
>>>
>>> Why don't you use NT_GNU_PROPERTY_TYPE_0?
>>
>> Ah, interesting. I hadn't seen this before. Docs I found were:
>> https://github.com/hjl-tools/linux-abi/commit/a24f6898c4172e09b2e476ae9f160621528a1d92
>>
>> \item[pr_datasz] The size of the \code{pr_data} field. A 4-byte
>> integer in the format of the target processor.
>> \item[pr_data] The program property descriptor. An array of 4-byte
>> integers in 32-bit object or 8-byte integers in 64-bit objects, in
>> the format of the target processor.
>>
>> Is pr_data length always a multiple of 4 (or 8)? I found this language
>
> Yes.
>
>> confusing, given that pr_datasz doesn't mention this.

Why does pr_padding exist if pr_data is always the correct multiple already?

>>
>> Also, given the definition, should the kernel examine these, or should
>> it remain limited to the runtimer loader?
>
> Both kernel and run-time loaders should check it. I am working on
> static PIE, which is loaded by kernel.

What kernel-support is needed for static PIE?

>
>> If the kernel should, would it be better to add
>> GNU_PROPERTY_EXEC_FLAGS, for future bits, or should it be something
>> like GNU_PROPERTY_NO_COPY_ON_PROTECTED with a pr_datasz == 0?
>
> Please use bits.

Okay.

> Is this an output only bit? Will it appear in an input file?

I believe this would only be an output bit, but I'm not sure how it
would be wired into binutils. Kostya, do you know any details about
how AddressSanitizer might be able to create this ELF note?

>> (And should the kernel already be parsing GNU_PROPERTY_STACK_SIZE?)
>
> Kernel should.

Have there been patches proposed for this yet?

Thanks!

-Kees

--
Kees Cook
Pixel Security

2017-08-09 19:01:15

by H.J. Lu

[permalink] [raw]
Subject: Re: new ELF marking

On Wed, Aug 9, 2017 at 11:52 AM, Kees Cook <[email protected]> wrote:
> On Wed, Aug 9, 2017 at 11:46 AM, H.J. Lu <[email protected]> wrote:
>> On Wed, Aug 9, 2017 at 11:26 AM, Kees Cook <[email protected]> wrote:
>>> On Wed, Aug 9, 2017 at 10:16 AM, H.J. Lu <[email protected]> wrote:
>>>> On Wed, Aug 9, 2017 at 10:07 AM, Kees Cook via binutils
>>>> <[email protected]> wrote:
>>>>> Hi,
>>>>>
>>>>> I'd like to be able to mark an ELF binary in such a way that Linux's
>>>>> binfmt_elf.c will collapse a PIE text area into the mmap region
>>>>> (currently they are separately randomized in memory). This is desired
>>>>> by AddressSanitizer to avoid having an ASan-built binary have its text
>>>>> area moving into an unexpected location[1] (ASLR is still desired, but
>>>>> doesn't need to have a PIE/mmap split).
>>>>>
>>>>> I see a few ways:
>>>>>
>>>>> - Add parsing for NOTE program headers and add a new NOTE type
>>>>> (NT_GNU_EXEC_FLAGS), though notes tend to be strings...
>>>>>
>>>>> - Add a new Program Header (GNU_EXEC_FLAGS), which is similar to how
>>>>> GNU_STACK and GNU_RELRO were handled. This could sort of be like NOTE
>>>>> except just lots of bit flags.
>>>>>
>>>>> - Use a filesystem xattr. This is fragile, in the case of copying
>>>>> binaries between systems or filesystems.
>>>>>
>>>>> Thoughts?
>>>>>
>>>>>
>>>>
>>>> Why don't you use NT_GNU_PROPERTY_TYPE_0?
>>>
>>> Ah, interesting. I hadn't seen this before. Docs I found were:
>>> https://github.com/hjl-tools/linux-abi/commit/a24f6898c4172e09b2e476ae9f160621528a1d92
>>>
>>> \item[pr_datasz] The size of the \code{pr_data} field. A 4-byte
>>> integer in the format of the target processor.
>>> \item[pr_data] The program property descriptor. An array of 4-byte
>>> integers in 32-bit object or 8-byte integers in 64-bit objects, in
>>> the format of the target processor.
>>>
>>> Is pr_data length always a multiple of 4 (or 8)? I found this language
>>
>> Yes.
>>
>>> confusing, given that pr_datasz doesn't mention this.
>
> Why does pr_padding exist if pr_data is always the correct multiple already?
>
>>>
>>> Also, given the definition, should the kernel examine these, or should
>>> it remain limited to the runtimer loader?
>>
>> Both kernel and run-time loaders should check it. I am working on
>> static PIE, which is loaded by kernel.
>
> What kernel-support is needed for static PIE?

Nothing so far:

[hjl@gnu-6 elf]$ readelf -l ./sln

Elf file type is DYN (Shared object file)
Entry point 0x8830
There are 8 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000a1466 0x00000000000a1466 R E 0x200000
LOAD 0x00000000000a2240 0x00000000002a2240 0x00000000002a2240
0x00000000000050a0 0x0000000000006590 RW 0x200000
DYNAMIC 0x00000000000a4d48 0x00000000002a4d48 0x00000000002a4d48
0x00000000000001a0 0x00000000000001a0 RW 0x8
NOTE 0x0000000000000200 0x0000000000000200 0x0000000000000200
0x0000000000000020 0x0000000000000020 R 0x4
TLS 0x00000000000a2240 0x00000000002a2240 0x00000000002a2240
0x0000000000000020 0x0000000000000060 R 0x8
GNU_EH_FRAME 0x0000000000096298 0x0000000000096298 0x0000000000096298
0x0000000000001a14 0x0000000000001a14 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x00000000000a2240 0x00000000002a2240 0x00000000002a2240
0x0000000000002dc0 0x0000000000002dc0 R 0x1

Section to Segment mapping:
Segment Sections...
00 .note.ABI-tag .hash .dynsym .dynstr .rela.dyn .rela.plt
.init .plt .plt.got .text __libc_freeres_fn __libc_thread_freeres_fn
.fini .rodata .eh_frame_hdr .eh_frame .gcc_except_table
01 .tdata .init_array .fini_array .data.rel.ro .dynamic .got
.got.plt .data __libc_subfreeres __libc_IO_vtables __libc_atexit
__libc_thread_subfreeres .bss __libc_freeres_ptrs
02 .dynamic
03 .note.ABI-tag
04 .tdata .tbss
05 .eh_frame_hdr
06
07 .tdata .init_array .fini_array .data.rel.ro .dynamic .got
[hjl@gnu-6 elf]$ ./sln
Usage: sln src dest|file

For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
[hjl@gnu-6 elf]$

>>> If the kernel should, would it be better to add
>>> GNU_PROPERTY_EXEC_FLAGS, for future bits, or should it be something
>>> like GNU_PROPERTY_NO_COPY_ON_PROTECTED with a pr_datasz == 0?
>>
>> Please use bits.
>
> Okay.
>
>> Is this an output only bit? Will it appear in an input file?
>
> I believe this would only be an output bit, but I'm not sure how it
> would be wired into binutils. Kostya, do you know any details about
> how AddressSanitizer might be able to create this ELF note?

if it is an output only bit, "-z fobar" should work, like

-z ibt Generate GNU_PROPERTY_X86_FEATURE_1_IBT
-z shstk Generate GNU_PROPERTY_X86_FEATURE_1_SHSTK

Or you can put it in the input file and linker will copy it to output, like
GNU_PROPERTY_STACK_SIZE.

>>> (And should the kernel already be parsing GNU_PROPERTY_STACK_SIZE?)
>>
>> Kernel should.
>
> Have there been patches proposed for this yet?
>

Not I am aware of.

--
H.J.

2017-08-09 20:32:47

by Kostya Serebryany

[permalink] [raw]
Subject: Re: new ELF marking

> >
> > I believe this would only be an output bit, but I'm not sure how it
> > would be wired into binutils. Kostya, do you know any details about
> > how AddressSanitizer might be able to create this ELF note?

I don't, hopefully H.J's suggestion works.
Will it be backward compatible?
(i.e. will the binaries built in the new way work on the old kernels?)

Thanks!

--kcc
>
>
> if it is an output only bit, "-z fobar" should work, like
>
> -z ibt Generate GNU_PROPERTY_X86_FEATURE_1_IBT
> -z shstk Generate GNU_PROPERTY_X86_FEATURE_1_SHSTK
>
> Or you can put it in the input file and linker will copy it to output, like
> GNU_PROPERTY_STACK_SIZE.

2017-08-09 21:24:35

by H.J. Lu

[permalink] [raw]
Subject: Re: new ELF marking

On Wed, Aug 9, 2017 at 1:32 PM, Kostya Serebryany <[email protected]> wrote:
>> >
>> > I believe this would only be an output bit, but I'm not sure how it
>> > would be wired into binutils. Kostya, do you know any details about
>> > how AddressSanitizer might be able to create this ELF note?
>
> I don't, hopefully H.J's suggestion works.
> Will it be backward compatible?
> (i.e. will the binaries built in the new way work on the old kernels?)
>
>

Yes, it is backward compatible by design.


--
H.J.

2017-08-09 22:37:40

by Carlos O'Donell

[permalink] [raw]
Subject: Re: new ELF marking

On 08/09/2017 05:24 PM, H.J. Lu wrote:
> On Wed, Aug 9, 2017 at 1:32 PM, Kostya Serebryany <[email protected]> wrote:
>>>>
>>>> I believe this would only be an output bit, but I'm not sure how it
>>>> would be wired into binutils. Kostya, do you know any details about
>>>> how AddressSanitizer might be able to create this ELF note?
>>
>> I don't, hopefully H.J's suggestion works.
>> Will it be backward compatible?
>> (i.e. will the binaries built in the new way work on the old kernels?)
>>
>>
>
> Yes, it is backward compatible by design.

... only as long as the semantics implied by the flags are hints that
can be ignored.

--
Cheers,
Carlos.