commit:     3287c2fa3e468949fe1663a0e35368a5af66f823
Author:     Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Thu Jun 19 01:18:44 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Thu Jun 19 18:13:10 2025 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=3287c2fa

emerge-webrsync: make die/exit behave properly in check_file_signature_gpg()

A recent commit introduced the ability for emerge-webrsync to ensure
that defunct gpg-agent(1) processes are terminated upon the
check_file_signature_gpg() function returning, provided that it was
tasked with creating an ephemeral keyring. However, it also introduced a
minor regression as concerns error handling and the conveyance of
diagnostic messages. Consider the following as a case in point.

fingerprint=$(gpg_fingerprint '<infrastructure <AT> gentoo.org>') \
|| die "couldn't find a fingerprint for the <infrastructure <AT> gentoo.org> 
key"

The intention is straightforward: should it prove impossible to obtain
the fingerprint of the applicable signing key then display a diagnostic
message before immediately exiting the program. Yet, because the
definition of the function is a compound command that incurs a subshell,
only the subshell will be exited. The function will then yield to its
caller, check_file_signature(), which responds as follows.

  die "signature verification failed for ${file@Q}"

Only then shall emerge-webrsync exit, resulting in an additional
diagnostic message being unintentionally shown.

 * Checking signature ...
emerge-webrsync: couldn't find a fingerprint for the <infrastructure <AT> 
gentoo.org> key
emerge-webrsync: signature verification failed for 'gentoo-20250617.tar.xz'

Address this issue in a manner twofold. Firstly, declare the function as
a compound command of the { … } form so as not to incur a subshell.
Secondly, delegate the responsibility for terminating gpg-agent(1) to
the EXIT trap that is already declared by the main() function.

Additionally, given that the trap is already responsible for wiping the
temporary directory, relocate the trap payload to a dedicated function
by the name of cleanup(). This helps to keep the code reasonably tidy.

Fixes: c9147587da34ecf6cd19bf1ed2d0835d3d8c1777
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>

 bin/emerge-webrsync | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
index 22df8ce635..a705a59eef 100755
--- a/bin/emerge-webrsync
+++ b/bin/emerge-webrsync
@@ -57,9 +57,12 @@ main() {
 
        mkdir -p "${PORTAGE_TMPDIR}/portage"
 
-       # Create a temporary directory whose subsequent removal is guaranteed.
-       tmpdir=
-       trap 'rm -rf -- "${tmpdir}"' EXIT
+       # The cleanup function shall terminate defunct gpg-agent(1) processes
+       # and remove the destructable temporary directory.
+       unset -v GNUPGHOME tmpdir
+       trap cleanup EXIT
+
+       # Create a destructable temporary directory and switch to it.
        tmpdir=$(mktemp -d -- "${PORTAGE_TMPDIR}/portage/webrsync.XXXXXX") \
        && cd -- "${tmpdir}" \
        || exit
@@ -88,6 +91,15 @@ main() {
        fi
 }
 
+cleanup() {
+       # Prevent gpg-agent(1) from lingering for ephemeral keyrings.
+       if [[ ${GNUPGHOME} && ! ${PORTAGE_GPG_DIR} ]]; then
+               gpgconf -K gpg-agent
+       fi
+
+       rm -rf -- "${tmpdir}"
+}
+
 usage() {
        cat <<-EOF
        Usage: $0 [options]
@@ -277,10 +289,9 @@ check_file_signature_gemato() {
        gemato "${gemato_args[@]}" -- "${signature}" "${file}"
 }
 
-check_file_signature_gpg() (
+check_file_signature_gpg() {
        local signature=$1 file=$2
        local fingerprint key
-       local -x GNUPGHOME
 
        if [[ -n ${PORTAGE_GPG_KEY} ]] ; then
                key="${PORTAGE_GPG_KEY}"
@@ -297,12 +308,13 @@ check_file_signature_gpg() (
                die "${key@Q} does not exist (or is not a file)"
        fi
 
+       export GNUPGHOME
+
        if [[ ! ${GNUPGHOME=${PORTAGE_GPG_DIR}} ]]; then
                # The PORTAGE_GPG_DIR variable is either unset or empty. Create
                # a temporary directory to contain an ephemeral keyring into
                # which Gentoo's distributed public key block shall be imported.
                GNUPGHOME=$(mktemp -d -- 
"${PORTAGE_TMPDIR}/portage/webrsync.XXXXXX") \
-               && trap 'gpgconf -K gpg-agent' EXIT \
                && gpg --batch --import "${key}" \
                || exit
 
@@ -317,7 +329,7 @@ check_file_signature_gpg() (
        fi
 
        gpg_verify "${signature}" "${file}"
-)
+}
 
 gpg_fingerprint() {
        local -a fields

Reply via email to