PIE/PIC Clang Defaults on Linux x86-64

Hi folks,

I recently noticed that clang and GCC differ on the default PIE/PIC flags. In particular, clang doesn’t default to PIE/PIC on Linux x86-64, and GCC does.

$ clang++ a.cpp && readelf -l a.out | egrep ‘(LOAD|VirtAddr)’
Type Offset VirtAddr PhysAddr
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000

$ g++ a.cpp && readelf -l a.out | egrep ‘(LOAD|VirtAddr)’
Type Offset VirtAddr PhysAddr

LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000

Are there any concerns about changing the clang default to emit PIC and pass PIE to the linker?

Also, using clang++ -fPIC -fPIE <...> doesn’t emit a PIE. Any opponents to making -fPIE imply passing -pie to the linker?

  • Mitch.

I’ll elaborate on this a bit more since it may not be coming across clearly:

a) gcc and clang differ here:

clang++/g++ -o foo.x foo.c -fPIE

gcc passes -pie to the linker and clang doesn’t. This mostly seems like an oversight that can be fixed.

b) gcc and clang differ here

clang++/g++ -o foo.x foo.c

where gcc defaults to -pie and pie code generation and clang doesn’t.

This is something where we should at least have the discussion. For what it’s worth my thought is that we should move to PIE by default for linux if, for not other reason, as the system compiler (gcc) already does this. We also already do this on android and in some sanitizer cases.

Anyone else have any thoughts?

Thanks!

-eric

I'll elaborate on this a bit more since it may not be coming across clearly:

a) gcc and clang differ here:

clang++/g++ -o foo.x foo.c -fPIE

gcc passes -pie to the linker and clang doesn't. This mostly seems like an
oversight that can be fixed.

b) gcc and clang differ here

clang++/g++ -o foo.x foo.c

where gcc defaults to -pie and pie code generation and clang doesn't.

This is something where we should at least have the discussion. For what
it's worth my thought is that we should move to PIE by default for linux
if, for not other reason, as the system compiler (gcc) already does this.
We also already do this on android and in some sanitizer cases.

Anyone else have any thoughts?

Thanks!

-eric

GCC 6 introduced a configure option --enable-default-pie (default -fPIE and -pie)
(gcc.gnu.org Git - gcc.git/commit )

Distributions can decide whether they want to enable it.

There are two questions:

(1) Do we want to make default-pie configurable (which requires a CMake option)
(2) Whether or not this is configurable, do we want Generic_GCC::isPIEDefault() to return true

At this point, it is probably that more distributions enable it by default.
So switching Generic_GCC::isPIEDefault() probably makes sense.
I want to avoid a CMake variable to reduce issues in testing.
(These CLANG_DEFAULT_* are a source of test instability.)

(I suspect some distributions already ship downstream patches to enable
-fPIE and -pie by default.)

(1) Do we want to make default-pie configurable (which requires a CMake option)

Personally, no.

(2) Whether or not this is configurable, do we want Generic_GCC::isPIEDefault() to return true

This sounds reasonable to me.

My opinion is similar to yours, having this be compile-time configurable with a CMake flag is painful. I’d rather just make the default be <whatever the majority of distro’s do>. Do we know of any way of enumerating the default without pulling the {debian, RHEL, fedora, ?} packages individually?

I’ll elaborate on this a bit more since it may not be coming across clearly:

a) gcc and clang differ here:

clang++/g++ -o foo.x foo.c -fPIE

gcc passes -pie to the linker and clang doesn’t. This mostly seems like an
oversight that can be fixed.

b) gcc and clang differ here

clang++/g++ -o foo.x foo.c

where gcc defaults to -pie and pie code generation and clang doesn’t.

This is something where we should at least have the discussion. For what
it’s worth my thought is that we should move to PIE by default for linux
if, for not other reason, as the system compiler (gcc) already does this.
We also already do this on android and in some sanitizer cases.

Anyone else have any thoughts?

Thanks!

-eric

GCC 6 introduced a configure option --enable-default-pie (default -fPIE and -pie)
(https://gcc.gnu.org/git/?p=gcc.git&a=commit;h=428b381275bc95032274440f02d7719225de2c17 )

Distributions can decide whether they want to enable it.

There are two questions:

(1) Do we want to make default-pie configurable (which requires a CMake option)

I have no strong opinions here.

(2) Whether or not this is configurable, do we want Generic_GCC::isPIEDefault() to return true

At this point I think so.

+Craig Topper for the x86 backend side of things in case he wants to comment.

-eric

Be careful about what systems this affects.

Joerg

Take this as netbsd isn’t one of those that want pie by default?

And yeah I think putting this next to the Android check (or modifying the Android check location) would be safest.

Yes, partially because it is known to break certain software, especially
with ASLR enabled.

Joerg

(2) Whether or not this is configurable, do we want Generic_GCC::isPIEDefault() to return true

Be careful about what systems this affects.

Joerg

We can change Linux::isPIEDefault() instead, assuming that NetBSD
doesn't like it:/

Take this as netbsd isn't one of those that want pie by default?

Yes, partially because it is known to break certain software, especially
with ASLR enabled.

Joerg

Actually, I don't like the idea of enable-default-pie (distribution
picks no-pie or pie default). I think they just lead to confusion and
unnecessary distribution differences (among Linux distros). They could
tune their default CFLAGS / CXXFLAGS / LDFLAGS instead.

For software like seabios, they have to add things like -no-pie -fno-pie
-fno-stack-protector -fno-stack-protector-all -fstack-check=no
-fcf-protection=none ...

Assuredly these enabled-by-default security features make some packagers
happy: wow, we have a good mechanism to force software to be secure (in their view).
They more or less neglected burden on downstream packages.