Add WITH_PIE knob to build Position Independent Executables

Building binaries as PIE allows the executable itself to be loaded at a
random address when ASLR is enabled (not just its shared libraries).

With this change PIE objects have a .pieo extension and INTERNALLIB
libraries libXXX_pie.a.

MK_PIE is disabled for some kerberos5 tools, Clang, and Subversion, as
they explicitly reference .a libraries in their Makefiles.  These can
be addressed on an individual basis later.  MK_PIE is also disabled for
rtld-elf because it is already position-independent using bespoke
Makefile rules.

Currently only dynamically linked binaries will be built as PIE.

Discussed with:	dim
Reviewed by:	kib
MFC after:	1 month
Relnotes:	Yes
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D18423
This commit is contained in:
Ed Maste 2019-02-15 22:22:38 +00:00
parent ca62461bc6
commit bcf99d2d99
13 changed files with 87 additions and 24 deletions

View File

@ -6,6 +6,7 @@ LIBROKEN_A= ${.OBJDIR:H:H}/lib/libroken/libroken.a
LIBADD= vers LIBADD= vers
LDADD= ${LIBROKEN_A} LDADD= ${LIBROKEN_A}
DPADD= ${LIBROKEN_A} DPADD= ${LIBROKEN_A}
MK_PIE:= no
SRCS= \ SRCS= \
asn1parse.y \ asn1parse.y \

View File

@ -6,6 +6,7 @@ LIBADD= vers
LDADD= ${LIBROKEN_A} LDADD= ${LIBROKEN_A}
DPADD= ${LIBROKEN_A} DPADD= ${LIBROKEN_A}
MAN= MAN=
MK_PIE:= no
SRCS= roken.h \ SRCS= roken.h \
slc-gram.y \ slc-gram.y \

View File

@ -2,6 +2,8 @@
.include <bsd.compiler.mk> .include <bsd.compiler.mk>
MK_PIE:= no # Explicit libXXX.a references
.if ${COMPILER_TYPE} == "clang" .if ${COMPILER_TYPE} == "clang"
DEBUG_FILES_CFLAGS= -gline-tables-only DEBUG_FILES_CFLAGS= -gline-tables-only
.else .else

View File

@ -7,6 +7,7 @@
.include <src.opts.mk> .include <src.opts.mk>
PACKAGE= clibs PACKAGE= clibs
MK_BIND_NOW= no MK_BIND_NOW= no
MK_PIE= no # Always position independent using local rules
MK_SSP= no MK_SSP= no
CONFS= libmap.conf CONFS= libmap.conf

View File

@ -91,13 +91,16 @@ CTFFLAGS+= -g
# prefer .s to a .c, add .po, remove stuff not used in the BSD libraries # prefer .s to a .c, add .po, remove stuff not used in the BSD libraries
# .pico used for PIC object files # .pico used for PIC object files
# .nossppico used for NOSSP PIC object files # .nossppico used for NOSSP PIC object files
.SUFFIXES: .out .o .bc .ll .po .pico .nossppico .S .asm .s .c .cc .cpp .cxx .C .f .y .l .ln # .pieo used for PIE object files
.SUFFIXES: .out .o .bc .ll .po .pico .nossppico .pieo .S .asm .s .c .cc .cpp .cxx .C .f .y .l .ln
.if !defined(PICFLAG) .if !defined(PICFLAG)
.if ${MACHINE_CPUARCH} == "sparc64" .if ${MACHINE_CPUARCH} == "sparc64"
PICFLAG=-fPIC PICFLAG=-fPIC
PIEFLAG=-fPIE
.else .else
PICFLAG=-fpic PICFLAG=-fpic
PIEFLAG=-fpie
.endif .endif
.endif .endif
@ -115,6 +118,10 @@ PO_FLAG=-pg
${CC} ${PICFLAG} -DPIC ${SHARED_CFLAGS:C/^-fstack-protector.*$//} ${CFLAGS:C/^-fstack-protector.*$//} -c ${.IMPSRC} -o ${.TARGET} ${CC} ${PICFLAG} -DPIC ${SHARED_CFLAGS:C/^-fstack-protector.*$//} ${CFLAGS:C/^-fstack-protector.*$//} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD} ${CTFCONVERT_CMD}
.c.pieo:
${CC} ${PIEFLAG} -DPIC ${SHARED_CFLAGS} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
.cc.po .C.po .cpp.po .cxx.po: .cc.po .C.po .cpp.po .cxx.po:
${CXX} ${PO_FLAG} ${STATIC_CXXFLAGS} ${PO_CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET} ${CXX} ${PO_FLAG} ${STATIC_CXXFLAGS} ${PO_CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
@ -124,6 +131,9 @@ PO_FLAG=-pg
.cc.nossppico .C.nossppico .cpp.nossppico .cxx.nossppico: .cc.nossppico .C.nossppico .cpp.nossppico .cxx.nossppico:
${CXX} ${PICFLAG} -DPIC ${SHARED_CXXFLAGS:C/^-fstack-protector.*$//} ${CXXFLAGS:C/^-fstack-protector.*$//} -c ${.IMPSRC} -o ${.TARGET} ${CXX} ${PICFLAG} -DPIC ${SHARED_CXXFLAGS:C/^-fstack-protector.*$//} ${CXXFLAGS:C/^-fstack-protector.*$//} -c ${.IMPSRC} -o ${.TARGET}
.cc.pieo .C.pieo .cpp.pieo .cxx.pieo:
${CXX} ${PIEFLAG} ${SHARED_CXXFLAGS} ${CXXFLAGS} -c ${.IMPSRC} -o ${.TARGET}
.f.po: .f.po:
${FC} -pg ${FFLAGS} -o ${.TARGET} -c ${.IMPSRC} ${FC} -pg ${FFLAGS} -o ${.TARGET} -c ${.IMPSRC}
${CTFCONVERT_CMD} ${CTFCONVERT_CMD}
@ -136,7 +146,7 @@ PO_FLAG=-pg
${FC} ${PICFLAG} -DPIC ${FFLAGS:C/^-fstack-protector.*$//} -o ${.TARGET} -c ${.IMPSRC} ${FC} ${PICFLAG} -DPIC ${FFLAGS:C/^-fstack-protector.*$//} -o ${.TARGET} -c ${.IMPSRC}
${CTFCONVERT_CMD} ${CTFCONVERT_CMD}
.s.po .s.pico .s.nossppico: .s.po .s.pico .s.nossppico .s.pieo:
${AS} ${AFLAGS} -o ${.TARGET} ${.IMPSRC} ${AS} ${AFLAGS} -o ${.TARGET} ${.IMPSRC}
${CTFCONVERT_CMD} ${CTFCONVERT_CMD}
@ -155,6 +165,11 @@ PO_FLAG=-pg
${CFLAGS:C/^-fstack-protector.*$//} ${ACFLAGS} -c ${.IMPSRC} -o ${.TARGET} ${CFLAGS:C/^-fstack-protector.*$//} ${ACFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD} ${CTFCONVERT_CMD}
.asm.pieo:
${CC:N${CCACHE_BIN}} -x assembler-with-cpp ${PIEFLAG} -DPIC \
${CFLAGS} ${ACFLAGS} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
.S.po: .S.po:
${CC:N${CCACHE_BIN}} -DPROF ${PO_CFLAGS} ${ACFLAGS} -c ${.IMPSRC} \ ${CC:N${CCACHE_BIN}} -DPROF ${PO_CFLAGS} ${ACFLAGS} -c ${.IMPSRC} \
-o ${.TARGET} -o ${.TARGET}
@ -170,6 +185,11 @@ PO_FLAG=-pg
-c ${.IMPSRC} -o ${.TARGET} -c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD} ${CTFCONVERT_CMD}
.S.pieo:
${CC:N${CCACHE_BIN}} ${PIEFLAG} -DPIC ${CFLAGS} ${ACFLAGS} \
-c ${.IMPSRC} -o ${.TARGET}
${CTFCONVERT_CMD}
_LIBDIR:=${LIBDIR} _LIBDIR:=${LIBDIR}
_SHLIBDIR:=${SHLIBDIR} _SHLIBDIR:=${SHLIBDIR}
@ -334,6 +354,20 @@ lib${LIB_PRIVATE}${LIB}_nossp_pic.a: ${NOSSPSOBJS}
.endif # !defined(INTERNALLIB) .endif # !defined(INTERNALLIB)
.if defined(INTERNALLIB) && ${MK_PIE} != "no"
PIEOBJS+= ${OBJS:.o=.pieo}
DEPENDOBJS+= ${PIEOBJS}
CLEANFILES+= ${PIEOBJS}
_LIBS+= lib${LIB_PRIVATE}${LIB}_pie.a
lib${LIB_PRIVATE}${LIB}_pie.a: ${PIEOBJS}
@${ECHO} building pie ${LIB} library
@rm -f ${.TARGET}
${AR} ${ARFLAGS} ${.TARGET} ${PIEOBJS} ${ARADD}
${RANLIB} ${RANLIBFLAGS} ${.TARGET}
.endif
.if defined(_SKIP_BUILD) .if defined(_SKIP_BUILD)
all: all:
.else .else

View File

@ -73,6 +73,7 @@ __DEFAULT_NO_OPTIONS = \
CCACHE_BUILD \ CCACHE_BUILD \
CTF \ CTF \
INSTALL_AS_USER \ INSTALL_AS_USER \
PIE \
RETPOLINE \ RETPOLINE \
STALE_STAGED STALE_STAGED

View File

@ -38,6 +38,12 @@ MK_DEBUG_FILES= no
.if ${MK_BIND_NOW} != "no" .if ${MK_BIND_NOW} != "no"
LDFLAGS+= -Wl,-znow LDFLAGS+= -Wl,-znow
.endif .endif
.if ${MK_PIE} != "no" && \
!defined(NO_SHARED) || ${NO_SHARED} == "no" || ${NO_SHARED} == "NO"
CFLAGS+= -fPIE
CXXFLAGS+= -fPIE
LDFLAGS+= -pie
.endif
.if ${MK_RETPOLINE} != "no" .if ${MK_RETPOLINE} != "no"
CFLAGS+= -mretpoline CFLAGS+= -mretpoline
CXXFLAGS+= -mretpoline CXXFLAGS+= -mretpoline

View File

@ -368,6 +368,10 @@ LDADD_atf_cxx= -lprivateatf-c++
LIB${_l:tu}?= ${LIBDESTDIR}${LIBDIR_BASE}/libprivate${_l}.a LIB${_l:tu}?= ${LIBDESTDIR}${LIBDIR_BASE}/libprivate${_l}.a
.endfor .endfor
.if ${MK_PIE} != "no"
PIE_SUFFIX= _pie
.endif
.for _l in ${_LIBRARIES} .for _l in ${_LIBRARIES}
.if ${_INTERNALLIBS:M${_l}} || !defined(SYSROOT) .if ${_INTERNALLIBS:M${_l}} || !defined(SYSROOT)
LDADD_${_l}_L+= -L${LIB${_l:tu}DIR} LDADD_${_l}_L+= -L${LIB${_l:tu}DIR}
@ -375,6 +379,8 @@ LDADD_${_l}_L+= -L${LIB${_l:tu}DIR}
DPADD_${_l}?= ${LIB${_l:tu}} DPADD_${_l}?= ${LIB${_l:tu}}
.if ${_PRIVATELIBS:M${_l}} .if ${_PRIVATELIBS:M${_l}}
LDADD_${_l}?= -lprivate${_l} LDADD_${_l}?= -lprivate${_l}
.elif ${_INTERNALLIBS:M${_l}}
LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l:S/${PIE_SUFFIX}//}${PIE_SUFFIX}
.else .else
LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l} LDADD_${_l}?= ${LDADD_${_l}_L} -l${_l}
.endif .endif
@ -418,69 +424,69 @@ LDADD+= ${LDADD_${_l}}
# INTERNALLIB definitions. # INTERNALLIB definitions.
LIBELFTCDIR= ${OBJTOP}/lib/libelftc LIBELFTCDIR= ${OBJTOP}/lib/libelftc
LIBELFTC?= ${LIBELFTCDIR}/libelftc.a LIBELFTC?= ${LIBELFTCDIR}/libelftc${PIE_SUFFIX}.a
LIBPEDIR= ${OBJTOP}/lib/libpe LIBPEDIR= ${OBJTOP}/lib/libpe
LIBPE?= ${LIBPEDIR}/libpe.a LIBPE?= ${LIBPEDIR}/libpe${PIE_SUFFIX}.a
LIBOPENBSDDIR= ${OBJTOP}/lib/libopenbsd LIBOPENBSDDIR= ${OBJTOP}/lib/libopenbsd
LIBOPENBSD?= ${LIBOPENBSDDIR}/libopenbsd.a LIBOPENBSD?= ${LIBOPENBSDDIR}/libopenbsd${PIE_SUFFIX}.a
LIBSMDIR= ${OBJTOP}/lib/libsm LIBSMDIR= ${OBJTOP}/lib/libsm
LIBSM?= ${LIBSMDIR}/libsm.a LIBSM?= ${LIBSMDIR}/libsm${PIE_SUFFIX}.a
LIBSMDBDIR= ${OBJTOP}/lib/libsmdb LIBSMDBDIR= ${OBJTOP}/lib/libsmdb
LIBSMDB?= ${LIBSMDBDIR}/libsmdb.a LIBSMDB?= ${LIBSMDBDIR}/libsmdb${PIE_SUFFIX}.a
LIBSMUTILDIR= ${OBJTOP}/lib/libsmutil LIBSMUTILDIR= ${OBJTOP}/lib/libsmutil
LIBSMUTIL?= ${LIBSMUTILDIR}/libsmutil.a LIBSMUTIL?= ${LIBSMUTILDIR}/libsmutil${PIE_SUFFIX}.a
LIBNETBSDDIR?= ${OBJTOP}/lib/libnetbsd LIBNETBSDDIR?= ${OBJTOP}/lib/libnetbsd
LIBNETBSD?= ${LIBNETBSDDIR}/libnetbsd.a LIBNETBSD?= ${LIBNETBSDDIR}/libnetbsd${PIE_SUFFIX}.a
LIBVERSDIR?= ${OBJTOP}/kerberos5/lib/libvers LIBVERSDIR?= ${OBJTOP}/kerberos5/lib/libvers
LIBVERS?= ${LIBVERSDIR}/libvers.a LIBVERS?= ${LIBVERSDIR}/libvers${PIE_SUFFIX}.a
LIBSLDIR= ${OBJTOP}/kerberos5/lib/libsl LIBSLDIR= ${OBJTOP}/kerberos5/lib/libsl
LIBSL?= ${LIBSLDIR}/libsl.a LIBSL?= ${LIBSLDIR}/libsl${PIE_SUFFIX}.a
LIBIPFDIR= ${OBJTOP}/sbin/ipf/libipf LIBIPFDIR= ${OBJTOP}/sbin/ipf/libipf
LIBIPF?= ${LIBIPFDIR}/libipf.a LIBIPF?= ${LIBIPFDIR}/libipf${PIE_SUFFIX}.a
LIBTELNETDIR= ${OBJTOP}/lib/libtelnet LIBTELNETDIR= ${OBJTOP}/lib/libtelnet
LIBTELNET?= ${LIBTELNETDIR}/libtelnet.a LIBTELNET?= ${LIBTELNETDIR}/libtelnet${PIE_SUFFIX}.a
LIBCRONDIR= ${OBJTOP}/usr.sbin/cron/lib LIBCRONDIR= ${OBJTOP}/usr.sbin/cron/lib
LIBCRON?= ${LIBCRONDIR}/libcron.a LIBCRON?= ${LIBCRONDIR}/libcron${PIE_SUFFIX}.a
LIBNTPDIR= ${OBJTOP}/usr.sbin/ntp/libntp LIBNTPDIR= ${OBJTOP}/usr.sbin/ntp/libntp
LIBNTP?= ${LIBNTPDIR}/libntp.a LIBNTP?= ${LIBNTPDIR}/libntp${PIE_SUFFIX}.a
LIBNTPEVENTDIR= ${OBJTOP}/usr.sbin/ntp/libntpevent LIBNTPEVENTDIR= ${OBJTOP}/usr.sbin/ntp/libntpevent
LIBNTPEVENT?= ${LIBNTPEVENTDIR}/libntpevent.a LIBNTPEVENT?= ${LIBNTPEVENTDIR}/libntpevent${PIE_SUFFIX}.a
LIBOPTSDIR= ${OBJTOP}/usr.sbin/ntp/libopts LIBOPTSDIR= ${OBJTOP}/usr.sbin/ntp/libopts
LIBOPTS?= ${LIBOPTSDIR}/libopts.a LIBOPTS?= ${LIBOPTSDIR}/libopts${PIE_SUFFIX}.a
LIBPARSEDIR= ${OBJTOP}/usr.sbin/ntp/libparse LIBPARSEDIR= ${OBJTOP}/usr.sbin/ntp/libparse
LIBPARSE?= ${LIBPARSEDIR}/libparse.a LIBPARSE?= ${LIBPARSEDIR}/libparse${PIE_SUFFIX}.a
LIBLPRDIR= ${OBJTOP}/usr.sbin/lpr/common_source LIBLPRDIR= ${OBJTOP}/usr.sbin/lpr/common_source
LIBLPR?= ${LIBLPRDIR}/liblpr.a LIBLPR?= ${LIBLPRDIR}/liblpr${PIE_SUFFIX}.a
LIBFIFOLOGDIR= ${OBJTOP}/usr.sbin/fifolog/lib LIBFIFOLOGDIR= ${OBJTOP}/usr.sbin/fifolog/lib
LIBFIFOLOG?= ${LIBFIFOLOGDIR}/libfifolog.a LIBFIFOLOG?= ${LIBFIFOLOGDIR}/libfifolog${PIE_SUFFIX}.a
LIBBSNMPTOOLSDIR= ${OBJTOP}/usr.sbin/bsnmpd/tools/libbsnmptools LIBBSNMPTOOLSDIR= ${OBJTOP}/usr.sbin/bsnmpd/tools/libbsnmptools
LIBBSNMPTOOLS?= ${LIBBSNMPTOOLSDIR}/libbsnmptools.a LIBBSNMPTOOLS?= ${LIBBSNMPTOOLSDIR}/libbsnmptools${PIE_SUFFIX}.a
LIBAMUDIR= ${OBJTOP}/usr.sbin/amd/libamu LIBAMUDIR= ${OBJTOP}/usr.sbin/amd/libamu
LIBAMU?= ${LIBAMUDIR}/libamu.a LIBAMU?= ${LIBAMUDIR}/libamu${PIE_SUFFIX}.a
LIBBE?= ${LIBBEDIR}/libbe.a LIBBE?= ${LIBBEDIR}/libbe${PIE_SUFFIX}.a
LIBPMCSTATDIR= ${OBJTOP}/lib/libpmcstat LIBPMCSTATDIR= ${OBJTOP}/lib/libpmcstat
LIBPMCSTAT?= ${LIBPMCSTATDIR}/libpmcstat.a LIBPMCSTAT?= ${LIBPMCSTATDIR}/libpmcstat${PIE_SUFFIX}.a
LIBC_NOSSP_PICDIR= ${OBJTOP}/lib/libc LIBC_NOSSP_PICDIR= ${OBJTOP}/lib/libc
LIBC_NOSSP_PIC?= ${LIBC_NOSSP_PICDIR}/libc_nossp_pic.a LIBC_NOSSP_PIC?= ${LIBC_NOSSP_PICDIR}/libc_nossp_pic.a

View File

@ -7,6 +7,7 @@
LOADER_ADDRESS?=0x200000 LOADER_ADDRESS?=0x200000
LDFLAGS+= -nostdlib LDFLAGS+= -nostdlib
LDFLAGS.lld+= -Wl,--no-rosegment LDFLAGS.lld+= -Wl,--no-rosegment
MK_PIE:= no
# BTX components # BTX components
BTXDIR= ${BOOTOBJ}/i386/btx BTXDIR= ${BOOTOBJ}/i386/btx

View File

@ -0,0 +1,3 @@
.\" $FreeBSD$
Do not build dynamically linked binaries as
Position-Independent Executable (PIE).

View File

@ -0,0 +1,3 @@
.\" $FreeBSD$
Build dynamically linked binaries as
Position-Independent Executable (PIE).

View File

@ -4,6 +4,8 @@ WARNS?= 0
.include <bsd.compiler.mk> .include <bsd.compiler.mk>
MK_PIE:= no # Explicit libXXX.a references
.if ${COMPILER_TYPE} == "clang" .if ${COMPILER_TYPE} == "clang"
DEBUG_FILES_CFLAGS= -gline-tables-only DEBUG_FILES_CFLAGS= -gline-tables-only
.else .else

View File

@ -2,6 +2,8 @@
.include <src.opts.mk> .include <src.opts.mk>
MK_PIE:= no # Explicit libXXX.a references
.if ${MK_SVN} == "yes" .if ${MK_SVN} == "yes"
SVNLITE?= SVNLITE?=
.else .else