tech-pkg archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Supporting MKPIE but without -pie embedded in wrapper scripts
Hello,
While trying to update lang/ghc90 to 9.0.2 and also enabling support for
PKGSRC_MKPIE, I found the way how the current infrastructure enforces
MKPIE rather cumbersome for packages that need to bootstrap from a
pre-built bootkit.
GHC bootkits consist of a compiler executable and the standard Haskell
library in the form of a set of static archives (lib*.a), which may or
may not be built with -fPIC. When lang/ghc90 is to be built, with
MKPIE_SUPPORTED set to yes, one of these things will happen:
1. Bootkit is built without -fPIC, and PKGSRC_MKPIE is set to no.
This builds non-PIE GHC fine.
2. Bootkit is built with -fPIC, and PKGSRC_MKPIE is set to yes.
This builds PIE GHC fine (with some tweaks applied to lang/ghc90).
3. Bootkit is built without -fPIC but PKGSRC_MKPIE is set to yes.
This fails to build the stage-1 compiler, which is an intermediate
compiler to build the final, stage-2 compiler that will be installed.
This is because pkgsrc forces -pie to be passed to the linker regardless
of compilation stages (because it doesn't know GHC does a 2-stage
bootstrapping), but the stage-1 compiler needs to be linked against
static libraries coming from the non-PIC bootkit.
4. Bootkit is built with -fPIC but PKGSRC_MKPIE is set to no.
This means we have no choice but to link a non-PIC stage-1
compiler *.o against static libraries from the bootkit built with -fPIC.
This apparently works, at least on NetBSD, but... you aren't supposed to
do that right? I don't know if this works on all the platforms we
currently support.
So, in order for packages like GHC to support MKPIE, we need a way to
tell pkgsrc that we are going to build PIE on our own responsibility but
not getting enforced by the infrastructure, such as injecting -pic in
linker flags, on per-package basis. But this of course means packages
that request an exemption from the enforcement can accidentally install
non-PIE, so a post-build check is desired.
The attached patch introduces a new package-settable variable
AUTOMATIC_MKPIE and a new check mentioned above. What do you think? Can
I commit this?
? fetch/sites.mk.back
Index: bsd.prefs.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/bsd.prefs.mk,v
retrieving revision 1.415
diff -u -r1.415 bsd.prefs.mk
--- bsd.prefs.mk 30 Nov 2021 09:39:11 -0000 1.415
+++ bsd.prefs.mk 16 Jan 2022 10:14:32 -0000
@@ -27,6 +27,16 @@
# directory. Typical values look like editors/emacs or
# misc/openoffice-bin.
#
+# Package-settable variables:
+#
+# AUTOMATIC_MKPIE
+# When this variable is set to yes, MKPIE is enforced through tool
+# wrappers. Setting it to no shifts the responsibility of building PIE
+# from the pkgsrc infrastructure to an individual package.
+#
+# Possible values: yes, no
+# Default value: yes
+#
# Keywords: mk.conf user platform
#
@@ -736,11 +746,12 @@
# Allows the security mitigation of ASLR to be used.
# Impact: very small performance drop.
#
-_PKGSRC_MKPIE= no
+AUTOMATIC_MKPIE?= yes
+_PKGSRC_MKPIE= no
.if ${PKGSRC_MKPIE:tl} == "yes" && \
${MKPIE_SUPPORTED:Uyes:tl} == "yes" && \
${_OPSYS_SUPPORTS_MKPIE:Uno} == "yes"
-_PKGSRC_MKPIE= yes
+_PKGSRC_MKPIE= yes
.endif
# Enable reproducible build flags
Index: cwrappers.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/cwrappers.mk,v
retrieving revision 1.31
diff -u -r1.31 cwrappers.mk
--- cwrappers.mk 7 May 2019 19:36:43 -0000 1.31
+++ cwrappers.mk 16 Jan 2022 10:14:32 -0000
@@ -89,9 +89,11 @@
${RUN}ln -s ${CWRAPPERS_SRC_DIR}/${CWRAPPERS_CONFIG.${wrappee}}-wrapper ${WRAPPER_BINDIR}/${alias}
. endfor
. if ${_PKGSRC_MKPIE} == "yes"
-. for arg in ${_MKPIE_LDFLAGS.gcc}
+. if ${AUTOMATIC_MKPIE:tl} == "yes"
+. for arg in ${_MKPIE_LDFLAGS.gcc}
${RUN}echo append_executable=${arg} >> ${CWRAPPERS_CONFIG_DIR}/${CWRAPPERS_CONFIG.${wrappee}}
-. endfor
+. endfor
+. endif
. endif
.endfor
Index: check/bsd.check-vars.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/check/bsd.check-vars.mk,v
retrieving revision 1.10
diff -u -r1.10 bsd.check-vars.mk
--- check/bsd.check-vars.mk 3 Oct 2017 09:43:06 -0000 1.10
+++ check/bsd.check-vars.mk 16 Jan 2022 10:14:32 -0000
@@ -6,6 +6,7 @@
#
CHECK_FILES_SUPPORTED?= yes
+CHECK_PIE_SUPPORTED?= yes
CHECK_RELRO_SUPPORTED?= yes
CHECK_SHLIBS_SUPPORTED?= yes
CHECK_SSP_SUPPORTED?= yes
Index: check/bsd.check.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/check/bsd.check.mk,v
retrieving revision 1.10
diff -u -r1.10 bsd.check.mk
--- check/bsd.check.mk 3 Oct 2017 09:43:06 -0000 1.10
+++ check/bsd.check.mk 16 Jan 2022 10:14:32 -0000
@@ -29,6 +29,7 @@
.include "check-headers.mk"
.include "check-interpreter.mk"
.include "check-perms.mk"
+.include "check-pie.mk"
.include "check-portability.mk"
.include "check-relro.mk"
.include "check-shlibs.mk"
Index: check/check-pie-elf.awk
===================================================================
RCS file: check/check-pie-elf.awk
diff -N check/check-pie-elf.awk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ check/check-pie-elf.awk 16 Jan 2022 10:14:32 -0000
@@ -0,0 +1,87 @@
+# $NetBSD$
+#
+# Read a list of potential ELF binaries from stdin. For each, extract the list
+# of headers. There are four possibilities:
+#
+# 1. Elf_Ehdr.e_type == ET_EXEC &&
+# PT_INTERP does not exist
+#
+# This is a statically-linked executable. Ignore these, as they cannot
+# ever be a PIE.
+#
+# 2. Elf_Ehdr.e_type == ET_EXEC &&
+# PT_INTERP exists in the program headers
+#
+# This is a dynamically-linked non-PIE that this script complains about.
+#
+# 3. Elf_Ehdr.e_type == ET_DYN &&
+# PT_INTERP exists in the program headers &&
+# DT_FLAGS_1 exists in the dynamic section &&
+# DT_FLAGS_1 contains DF_1_PIE
+#
+# This is a PIE.
+#
+# 4. Elf_Ehdr.e_type == ET_DYN &&
+# PT_INTERP does not exist in the program headers
+#
+# This is a shared object.
+#
+# See also https://stackoverflow.com/a/55704865
+#
+
+function shquote(IN, out) {
+ out = IN;
+ gsub("\\\\", "\\\\", out);
+ gsub("\\\n", "\\n", out);
+ gsub("\\\t", "\\t", out);
+ gsub(" ", "\\ ", out);
+ gsub("'", "\\'", out);
+ gsub("`", "\\`", out);
+ gsub("\"", "\\\"", out);
+ gsub(";", "\\;", out);
+ gsub("&", "\\&", out);
+ gsub("<", "\\<", out);
+ gsub(">", "\\>", out);
+ gsub("\\(", "\\(", out);
+ gsub("\\)", "\\)", out);
+ gsub("\\|", "\\|", out);
+ gsub("\\*", "\\*", out);
+ gsub("\\?", "\\?", out);
+ gsub("\\{", "\\{", out);
+ gsub("\\}", "\\}", out);
+ gsub("\\[", "\\[", out);
+ gsub("\\]", "\\]", out);
+ gsub("\\$", "\\$", out);
+ gsub("!", "\\!", out);
+ gsub("#", "\\#", out);
+ gsub("\\^", "\\^", out);
+ gsub("~", "\\~", out);
+ return out;
+}
+
+function check_pie(ELF, is_non_pie, is_dyn_exec) {
+ is_non_pie = 0;
+ is_dyn_exec = 0;
+ cmd = readelf " -Whl " shquote(ELF) " 2>/dev/null";
+ while ((cmd | getline) > 0) {
+ if ($1 == "Type:" && $2 == "EXEC") {
+ is_non_pie = 1;
+ }
+ else if ($1 == "INTERP") {
+ is_dyn_exec = 1;
+ }
+ }
+ close(cmd);
+ if (is_non_pie == 1 && is_dyn_exec == 1) {
+ print ELF ": not a PIE";
+ }
+}
+
+BEGIN {
+ readelf = ENVIRON["READELF"];
+ if (readelf == "") {
+ readelf = "readelf";
+ }
+}
+
+{ check_pie($0); }
Index: check/check-pie.mk
===================================================================
RCS file: check/check-pie.mk
diff -N check/check-pie.mk
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ check/check-pie.mk 16 Jan 2022 10:14:32 -0000
@@ -0,0 +1,75 @@
+# $NetBSD
+#
+# This file verifies that MKPIE (position-independent executables) was applied
+# accordingly at build-time.
+#
+# User-settable variables:
+#
+# CHECK_PIE
+# Whether the check should be enabled or not.
+#
+# Default value: "yes" for PKG_DEVELOPERs, "no" otherwise.
+#
+# Package-settable variables:
+#
+# CHECK_PIE_SKIP
+# A list of shell patterns (like man/*) that should be excluded
+# from the check. Note that a * in a pattern also matches a slash
+# in a pathname.
+#
+# Default value: empty.
+#
+# CHECK_PIE_SUPPORTED
+# Whether the check should be enabled for this package or not.
+#
+# Default value: yes
+#
+
+_VARGROUPS+= check-pie
+_USER_VARS.check-pie= CHECK_PIE
+_PKG_VARS.check-pie= CHECK_PIE_SUPPORTED
+
+.if ${_PKGSRC_MKPIE:Uno} != "no" && ${PKG_DEVELOPER:Uno:tl} != "no"
+CHECK_PIE?= yes
+.else
+CHECK_PIE?= no
+.endif
+CHECK_PIE_SUPPORTED?= yes
+CHECK_PIE_SKIP?= # none
+
+# All binaries but not libraries
+_CHECK_PIE_ERE= (bin/|sbin/|libexec/)
+
+_CHECK_PIE_FILELIST_CMD?= \
+ ${SED} -e '/^@/d' ${PLIST} | \
+ while read file; do \
+ ${TEST} -h "$$file" || ${ECHO} "$$file"; \
+ done
+
+_CHECK_PIE_CMD= # empty
+.if ${OBJECT_FMT} == "ELF"
+USE_TOOLS+= awk readelf
+_CHECK_PIE_CMD= ${AWK} -f ${PKGSRCDIR}/mk/check/check-pie-elf.awk
+_CHECK_PIE_ENV+= READELF=${TOOLS_PATH.readelf:Q}
+.endif
+
+.if ${CHECK_PIE:tl} == "yes" && \
+ ${CHECK_PIE_SUPPORTED:tl} == "yes" && \
+ !empty(_CHECK_PIE_CMD)
+privileged-install-hook: _check-pie
+_check-pie: error-check .PHONY
+ @${STEP_MSG} "Checking for PIE in ${PKGNAME}"
+ ${RUN} rm -f ${ERROR_DIR}/${.TARGET}
+ ${RUN} \
+ cd ${DESTDIR:Q}${PREFIX:Q}; \
+ ${_CHECK_PIE_FILELIST_CMD} | \
+ ${EGREP} -h ${_CHECK_PIE_ERE:Q} | \
+ while read file; do \
+ case "$$file" in \
+ ${CHECK_PIE_SKIP:@p@${p}) continue;;@} \
+ *) ${ECHO} "$$file"; \
+ esac; \
+ done | \
+ ${PKGSRC_SETENV} ${_CHECK_PIE_ENV} ${_CHECK_PIE_CMD} \
+ > ${ERROR_DIR}/${.TARGET}
+.endif
Index: compiler/gcc.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/compiler/gcc.mk,v
retrieving revision 1.234
diff -u -r1.234 gcc.mk
--- compiler/gcc.mk 22 Dec 2021 10:14:27 -0000 1.234
+++ compiler/gcc.mk 16 Jan 2022 10:14:32 -0000
@@ -352,6 +352,7 @@
# XXX for libraries a sink wrapper around gcc is required and used instead
_MKPIE_LDFLAGS.gcc= -pie
+. if ${AUTOMATIC_MKPIE:tl} == "yes"
_GCC_CFLAGS+= ${_MKPIE_CFLAGS.gcc}
_GCC_FCFLAGS+= ${_MKPIE_FCFLAGS.gcc}
#_GCC_LDFLAGS+= ${_MKPIE_LDFLAGS.gcc}
@@ -360,6 +361,7 @@
CWRAPPERS_APPEND.f77+= ${_MKPIE_FCFLAGS.gcc}
# this differs for libraries and executables (handled in mk/cwrappers.mk)
# CWRAPPERS_APPEND.ld+= ${_MKPIE_LDFLAGS.gcc}
+. endif
.endif
.if ${_PKGSRC_MKREPRO} == "yes"
Index: wrapper/bsd.wrapper.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/wrapper/bsd.wrapper.mk,v
retrieving revision 1.102
diff -u -r1.102 bsd.wrapper.mk
--- wrapper/bsd.wrapper.mk 27 Apr 2020 05:23:11 -0000 1.102
+++ wrapper/bsd.wrapper.mk 16 Jan 2022 10:14:32 -0000
@@ -304,7 +304,7 @@
.if !empty(PKGSRC_COMPILER:Mgcc)
_WRAP_TRANSFORM.CC= ${WRAPPER_TMPDIR}/transform-gcc
_WRAP_TRANSFORM.CXX= ${_WRAP_TRANSFORM.CC}
-. if ${_PKGSRC_MKPIE} != "no"
+. if ${_PKGSRC_MKPIE} != "no" && ${AUTOMATIC_MKPIE:tl} != "no"
_WRAP_CMD_SINK.CC= ${WRAPPER_TMPDIR}/cmd-sink-mkpie-gcc
_WRAP_CMD_SINK.CXX= ${_WRAP_CMD_SINK.CC}
_WRAP_CMD_SINK.LD= ${WRAPPER_TMPDIR}/cmd-sink-mkpie-ld
Home |
Main Index |
Thread Index |
Old Index