From 1cfcc888d317e43de6a3daa34329309ad650c5a9 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 25 Mar 2026 10:14:12 +0000 Subject: [PATCH 1/4] Basic PIE downloader flag --with-pie --- configure.ac | 34 +++++++++++++++++++++++++++++++++- pie/Makefile.frag | 34 ++++++++++++++++++++++++++++++++++ pie/README.md | 12 ++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 pie/Makefile.frag create mode 100644 pie/README.md diff --git a/configure.ac b/configure.ac index 07e64e74887c3..ef30323ec5103 100644 --- a/configure.ac +++ b/configure.ac @@ -1182,6 +1182,38 @@ AS_VAR_IF([PHP_PEAR], [no],, [ [pear]) ]) +dnl PIE +dnl ---------------------------------------------------------------------------- + +PHP_HELP_SEPARATOR([PIE:]) +PHP_CONFIGURE_PART([Configuring PIE]) + +dnl If CLI is disabled disable PIE. +AS_VAR_IF([PHP_CLI], [no], [with_pie=no]) + +PHP_ARG_WITH([pie], + [whether to install PIE], + [AS_HELP_STRING([[--with-pie[=DIR]]], + [Install PIE in DIR [PREFIX/lib/php]])], + [no], + [yes]) + +AS_VAR_IF([PHP_PIE], [no],, [ + install_pie=install-pie + + AS_VAR_IF([PHP_PIE], [yes], + [AS_CASE([$PHP_LAYOUT], + [GNU], [PIE_INSTALLDIR=$datadir/pie], + [PIE_INSTALLDIR=$libdir/php])], + [PIE_INSTALLDIR=$PHP_PIE]) + + PHP_SUBST([PIE_INSTALLDIR]) + PHP_ADD_BUILD_DIR([pie]) + PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/pie/Makefile.frag], + [$abs_srcdir/pie], + [pie]) +]) + dnl Configuring Zend and TSRM. dnl ---------------------------------------------------------------------------- @@ -1622,7 +1654,7 @@ else fi; all_targets="\$(OVERALL_TARGET) \$(PHP_MODULES) \$(PHP_ZEND_EX) \$(PHP_BINARIES) $pharcmd" -install_targets="$install_sapi $install_modules $install_binaries install-build install-headers install-programs $install_pear $pharcmd_install" +install_targets="$install_sapi $install_modules $install_binaries install-build install-headers install-programs $install_pear $install_pie $pharcmd_install" PHP_SUBST([all_targets]) PHP_SUBST([install_targets]) diff --git a/pie/Makefile.frag b/pie/Makefile.frag new file mode 100644 index 0000000000000..c3cd363ea255a --- /dev/null +++ b/pie/Makefile.frag @@ -0,0 +1,34 @@ +piedir=$(PIE_INSTALLDIR) + +PIE_PHP_FLAGS = -dmemory_limit=-1 + +CURL = `which curl 2>/dev/null` +WGET = `which wget 2>/dev/null` +FETCH = `which fetch 2>/dev/null` +GH = `which gh 2>/dev/null` +PIE_PHAR_URL = https://github.com/php/pie/releases/latest/download/pie.phar + +PIE_PHAR_DESTINATION = $(INSTALL_ROOT)$(piedir)/pie + +$(PIE_PHAR_DESTINATION): + @echo "Installing PIE: $(PIE_PHAR_DESTINATION)" + @if test ! -z "$(CURL)" && test -x "$(CURL)"; then \ + "$(CURL)" --no-progress-meter --silent --location "${PIE_PHAR_URL}" --output $(PIE_PHAR_DESTINATION); \ + elif test ! -z "$(WGET)" && test -x "$(WGET)"; then \ + "$(WGET)" "${PIE_PHAR_URL}" --quiet --no-directories --output-document=$(PIE_PHAR_DESTINATION); \ + elif test ! -z "$(FETCH)" && test -x "$(FETCH)"; then \ + "$(FETCH)" -o $(PIE_PHAR_DESTINATION) "${PIE_PHAR_URL}"; \ + else \ + $(top_builddir)/sapi/cli/php -n $(top_srcdir)/pear/fetch.php "${PIE_PHAR_URL}" $(PIE_PHAR_DESTINATION) ; \ + fi + @if test ! -z "$(GH)" && test -x "$(GH)"; then \ + "$(GH)" attestation verify --owner=php $(PIE_PHAR_DESTINATION); \ + else \ + $(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) self-verify; \ + fi + @chmod +x $(PIE_PHAR_DESTINATION) + +.PHONY: install-pie +install-pie: $(PIE_PHAR_DESTINATION) + @$(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) self-update > /dev/null 2>&1 + @$(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) --version diff --git a/pie/README.md b/pie/README.md new file mode 100644 index 0000000000000..b385c1ee8ab66 --- /dev/null +++ b/pie/README.md @@ -0,0 +1,12 @@ +# PIE downloader + +When building PHP, supply the `--with-pie` flag. This will attempt to download +the latest stable version of PIE, using `curl`, `wget`, `fetch`, or a PHP script. + +By default it will download PIE to `$prefix/lib/php/pie`. You can change +the target path, e.g. `--with-pie=/usr/local/bin`, which will cause PIE to be +downloaded to `/usr/local/bin/pie`. + +If the `gh` CLI tool exists on the system, it will be used to verify that the +PIE that is downloaded was built within PHP's CI system. If not, the +`pie self-verify` command is used, but this has limited benefit. From 93bdfd13b217ce1f8e367a649df414d63e3db36a Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 26 Mar 2026 07:14:22 +0000 Subject: [PATCH 2/4] Move PIE to install in $(bindir) --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index ef30323ec5103..ffde635f62810 100644 --- a/configure.ac +++ b/configure.ac @@ -1203,8 +1203,8 @@ AS_VAR_IF([PHP_PIE], [no],, [ AS_VAR_IF([PHP_PIE], [yes], [AS_CASE([$PHP_LAYOUT], - [GNU], [PIE_INSTALLDIR=$datadir/pie], - [PIE_INSTALLDIR=$libdir/php])], + [GNU], [PIE_INSTALLDIR=$bindir], + [PIE_INSTALLDIR=$bindir])], [PIE_INSTALLDIR=$PHP_PIE]) PHP_SUBST([PIE_INSTALLDIR]) From 742c94076d2c533d47665e8cb07c1c9fd1f30d55 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 26 Mar 2026 07:28:40 +0000 Subject: [PATCH 3/4] Download PIE to a temp directory before verifying --- configure.ac | 2 +- pie/Makefile.frag | 28 +++++++++++++++++++++------- pie/README.md | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index ffde635f62810..cea4508842aad 100644 --- a/configure.ac +++ b/configure.ac @@ -1194,7 +1194,7 @@ AS_VAR_IF([PHP_CLI], [no], [with_pie=no]) PHP_ARG_WITH([pie], [whether to install PIE], [AS_HELP_STRING([[--with-pie[=DIR]]], - [Install PIE in DIR [PREFIX/lib/php]])], + [Install PIE in DIR [PREFIX/bin]])], [no], [yes]) diff --git a/pie/Makefile.frag b/pie/Makefile.frag index c3cd363ea255a..697bc8af62ca1 100644 --- a/pie/Makefile.frag +++ b/pie/Makefile.frag @@ -5,30 +5,44 @@ PIE_PHP_FLAGS = -dmemory_limit=-1 CURL = `which curl 2>/dev/null` WGET = `which wget 2>/dev/null` FETCH = `which fetch 2>/dev/null` +FETCH_PHP = $(top_srcdir)/pear/fetch.php GH = `which gh 2>/dev/null` PIE_PHAR_URL = https://github.com/php/pie/releases/latest/download/pie.phar - +PIE_PHAR_TEMP_DL_LOCATION = $(top_srcdir)/pie/pie_temp.phar PIE_PHAR_DESTINATION = $(INSTALL_ROOT)$(piedir)/pie $(PIE_PHAR_DESTINATION): @echo "Installing PIE: $(PIE_PHAR_DESTINATION)" +# First, figure out a way to download the phar, with curl, wget, fetch, or a backup PHP script... @if test ! -z "$(CURL)" && test -x "$(CURL)"; then \ - "$(CURL)" --no-progress-meter --silent --location "${PIE_PHAR_URL}" --output $(PIE_PHAR_DESTINATION); \ + echo " downloading ${PIE_PHAR_URL} with ${CURL} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ + "$(CURL)" --no-progress-meter --silent --location "${PIE_PHAR_URL}" --output $(PIE_PHAR_TEMP_DL_LOCATION); \ elif test ! -z "$(WGET)" && test -x "$(WGET)"; then \ - "$(WGET)" "${PIE_PHAR_URL}" --quiet --no-directories --output-document=$(PIE_PHAR_DESTINATION); \ + echo " downloading ${PIE_PHAR_URL} with ${WGET} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ + "$(WGET)" "${PIE_PHAR_URL}" --quiet --no-directories --output-document=$(PIE_PHAR_TEMP_DL_LOCATION); \ elif test ! -z "$(FETCH)" && test -x "$(FETCH)"; then \ - "$(FETCH)" -o $(PIE_PHAR_DESTINATION) "${PIE_PHAR_URL}"; \ + echo " downloading ${PIE_PHAR_URL} with ${FETCH} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ + "$(FETCH)" -o $(PIE_PHAR_TEMP_DL_LOCATION) "${PIE_PHAR_URL}"; \ else \ - $(top_builddir)/sapi/cli/php -n $(top_srcdir)/pear/fetch.php "${PIE_PHAR_URL}" $(PIE_PHAR_DESTINATION) ; \ + echo " downloading ${PIE_PHAR_URL} with ${FETCH_PHP} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ + $(top_builddir)/sapi/cli/php -n "${FETCH_PHP}" "${PIE_PHAR_URL}" $(PIE_PHAR_TEMP_DL_LOCATION) ; \ fi +# Try to verify using `gh` CLI, or if not use `self-verify` (which isn't the best, since it could already have been tampered) @if test ! -z "$(GH)" && test -x "$(GH)"; then \ - "$(GH)" attestation verify --owner=php $(PIE_PHAR_DESTINATION); \ + echo " verifying ${PIE_PHAR_TEMP_DL_LOCATION} with ${GH}"; \ + "$(GH)" attestation verify --owner=php $(PIE_PHAR_TEMP_DL_LOCATION); \ else \ - $(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) self-verify; \ + echo " verifying ${PIE_PHAR_TEMP_DL_LOCATION} with self-verify (insecure)"; \ + $(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_TEMP_DL_LOCATION) self-verify; \ fi +# Once verified, move it to the real location + @echo " move ${PIE_PHAR_TEMP_DL_LOCATION} to ${PIE_PHAR_DESTINATION}" + @mv $(PIE_PHAR_TEMP_DL_LOCATION) $(PIE_PHAR_DESTINATION) @chmod +x $(PIE_PHAR_DESTINATION) .PHONY: install-pie install-pie: $(PIE_PHAR_DESTINATION) + @echo " self-updating ${PIE_PHAR_DESTINATION}" @$(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) self-update > /dev/null 2>&1 + @echo " checking version ${PIE_PHAR_DESTINATION}" @$(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) --version diff --git a/pie/README.md b/pie/README.md index b385c1ee8ab66..0b273cda9d295 100644 --- a/pie/README.md +++ b/pie/README.md @@ -3,7 +3,7 @@ When building PHP, supply the `--with-pie` flag. This will attempt to download the latest stable version of PIE, using `curl`, `wget`, `fetch`, or a PHP script. -By default it will download PIE to `$prefix/lib/php/pie`. You can change +By default it will download PIE to `$prefix/bin/pie`. You can change the target path, e.g. `--with-pie=/usr/local/bin`, which will cause PIE to be downloaded to `/usr/local/bin/pie`. From ce67233bbf4b41d6105730edced72e899c33dae7 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 26 Mar 2026 08:20:04 +0000 Subject: [PATCH 4/4] Removed pie installer debug echo statements --- pie/Makefile.frag | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pie/Makefile.frag b/pie/Makefile.frag index 697bc8af62ca1..3c4a1739b3fb9 100644 --- a/pie/Makefile.frag +++ b/pie/Makefile.frag @@ -15,34 +15,25 @@ $(PIE_PHAR_DESTINATION): @echo "Installing PIE: $(PIE_PHAR_DESTINATION)" # First, figure out a way to download the phar, with curl, wget, fetch, or a backup PHP script... @if test ! -z "$(CURL)" && test -x "$(CURL)"; then \ - echo " downloading ${PIE_PHAR_URL} with ${CURL} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ "$(CURL)" --no-progress-meter --silent --location "${PIE_PHAR_URL}" --output $(PIE_PHAR_TEMP_DL_LOCATION); \ elif test ! -z "$(WGET)" && test -x "$(WGET)"; then \ - echo " downloading ${PIE_PHAR_URL} with ${WGET} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ "$(WGET)" "${PIE_PHAR_URL}" --quiet --no-directories --output-document=$(PIE_PHAR_TEMP_DL_LOCATION); \ elif test ! -z "$(FETCH)" && test -x "$(FETCH)"; then \ - echo " downloading ${PIE_PHAR_URL} with ${FETCH} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ "$(FETCH)" -o $(PIE_PHAR_TEMP_DL_LOCATION) "${PIE_PHAR_URL}"; \ else \ - echo " downloading ${PIE_PHAR_URL} with ${FETCH_PHP} to ${PIE_PHAR_TEMP_DL_LOCATION}"; \ $(top_builddir)/sapi/cli/php -n "${FETCH_PHP}" "${PIE_PHAR_URL}" $(PIE_PHAR_TEMP_DL_LOCATION) ; \ fi # Try to verify using `gh` CLI, or if not use `self-verify` (which isn't the best, since it could already have been tampered) @if test ! -z "$(GH)" && test -x "$(GH)"; then \ - echo " verifying ${PIE_PHAR_TEMP_DL_LOCATION} with ${GH}"; \ "$(GH)" attestation verify --owner=php $(PIE_PHAR_TEMP_DL_LOCATION); \ else \ - echo " verifying ${PIE_PHAR_TEMP_DL_LOCATION} with self-verify (insecure)"; \ $(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_TEMP_DL_LOCATION) self-verify; \ fi # Once verified, move it to the real location - @echo " move ${PIE_PHAR_TEMP_DL_LOCATION} to ${PIE_PHAR_DESTINATION}" @mv $(PIE_PHAR_TEMP_DL_LOCATION) $(PIE_PHAR_DESTINATION) @chmod +x $(PIE_PHAR_DESTINATION) .PHONY: install-pie install-pie: $(PIE_PHAR_DESTINATION) - @echo " self-updating ${PIE_PHAR_DESTINATION}" @$(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) self-update > /dev/null 2>&1 - @echo " checking version ${PIE_PHAR_DESTINATION}" @$(top_builddir)/sapi/cli/php $(PIE_PHP_FLAGS) $(PIE_PHAR_DESTINATION) --version