Page MenuHome GnuPG

pinentry-tty & pinentry-curses breaks tty when timeout occurs or CTRL-C is pressed
Closed, ResolvedPublic

Description

Hello together,

We are utilizing a setup that incorporates SOPS, GnuPG, and Pinentry to manage our secrets within a Docker Image (yes, GPG_TTY should be set correctly), but SOPS is utilizing the hosts gpg-agent / pinentry. We are encountering an issue that we already spent some time investigating, but without luck.

  • If the pinentry (or specifically GnuPG) prompt times out or if we interrupt it using CTRL+C, the terminal becomes non-responsive and fails to display keystrokes, any output is mis-aligned/garbled, after another ~60 seconds the faulty bahaviour stops.
  • When initiating multiple sessions within the same image and allowing GnuPG to time out first, the GnuPG prompt unexpectedly appears in a different shell session when run again on the initial session.

Our internal testing has confirmed that this issue aligns with the one described at https://dev.gnupg.org/T4585
We've also observed that after a GPG timeout (or receiving SIGINT), while the agent process terminates as expected, the pinentry process remains active. Terminating the pinentry process manually restores normal terminal functionality.

We've also confirmed this behavior with pinentry-1.1.1 through the latest beta. Aside from having our keys imported there's no additional config done from our side.

I can happily provide more information / output if needed.

Kind regards,
Yannick

Event Timeline

ydixken created this object in space S1 Public.
ydixken renamed this task from pinentry-tty breaks tty when timeout occurs or CTRL-C is pressed to pinentry-tty & pinentry-curses breaks tty when timeout occurs or CTRL-C is pressed.Aug 10 2023, 10:04 AM
ydixken updated the task description. (Show Details)
gniibe triaged this task as Normal priority.
gniibe added a subscriber: gniibe.

Thank you for the report.
I found a bug in pinentry-curses and pinentry-tty for handling SIGINT. I am going to fix this.

Please note that older GnuPG does not have the fix of T4585.
In GnuPG 2.4 or later, gpg-agent should kill the pinentry process correctly.

Pushed the fix for SIGINT handling of pinentry-tty and pinentry-curses by: rPa6f63fe37dbf: tty,curses: Upon SIGINT, let pinentry exit gracefully.
This fix should improve the situation.

For other cases, could you please minimize the issue? There may be multiple issues.
To identify a bug, please do your tests for each case:

  • timeout behavior
    • when you specify timeout for pinentry, does it correctly raise an error?
  • killing by CTRL-C
    • it kills gpg (the frontend command). gpg-agent (in GnuPG 2.4) should notice the finish of gpg and should kill pinentry correctly by SIGINT
    • pinentry-{tty|curses} should die by SIGINT, restoring terminal

Otherwise, use of --pinentry-mode=loopback is simpler, as it never invokes pinentry (gpg-agent asks back to gpg frontend).

Hi @gniibe - thanks for your fix.

I've applied the patch locally, built and replaced the binaries, but still don't see any improvement of the SIGINT handling, can confirm this for pinentry-tty & pinentry-curses.

I can also reproduce the error locally using a plain Ubuntu.

For pinentry-tty:

ydixken@master:~$ gpg --decrypt foo.gpg
Please enter the passphrase to unlock the OpenPGP secret key:
"Yannick Michél Dixken <yannick@redacted.de>"
4096-bit RSA key, ID 552A686A35B20895,
created 2022-06-01 (main key ID 855CFCB16D8B4D90).

Passphrase:

*CTRL+C pressed..*

gpg: signal 2 caught ... exiting

The calling terminal is now broken until the timeout runs out.

ydixken@master:~/pinentry$ ps aux | grep pinen
ydixken 219860 0.0 0.0 3092 1232 ? SL 13:07 0:00 pinentry <== still running
ydixken 219951 0.0 0.0 8524 2236 pts/0 S+ 13:08 0:00 grep --color=auto pinen

ydixken@master:~/pinentry$ lsof -p 220028
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
pinentry 220028 ydixken cwd DIR 8,1 4096 4501 /home/ydixken
pinentry 220028 ydixken rtd DIR 8,1 4096 2 /
pinentry 220028 ydixken txt REG 8,1 177424 796 /usr/bin/pinentry-tty <=== confirmed to be my build containing your patch.

Same behaviour with pinentry-curses.

The timeout seems to work correctly.

Using Ubuntu, it's GnuPG 2.2 (which doesn't have the fix of T4585). Without the fix, killing gpg (by CTRL-C) causes problematic situation where pinentry remains asking.
That's because gpg-agent and pinentry don't know the frontend side has been killed. T4585 introduced a watching thread into gpg-agent, so that it can correctly detect lost of frontend.

We should not backport this to 2.2; better update to the current stable version (2.4)

gniibe changed the task status from Open to Testing.Dec 27 2023, 1:33 AM

Fixed in pinentry 1.3, when using GnuPG 2.4 or later.