Page MenuHome GnuPG

way to not spawn (or despawn) gpg-agent and dirmngr
Closed, WontfixPublic

Description

Hi,
I found an issue today that was bugging me.
After a lot of debugging I think I now have a TL;DR that can be discussed.

Simply running the follwing spawns a dirmngr/agent daemon:
gpg --keyserver hkp://keyserver.ubuntu.com:80/ --recv
04450970750A7228C042CD4442C3EB37B6832E30

After that I find this on the system:
gpg-agent --homedir /root/.gnupg --use-standard-socket --daemon

I found that the old way to disable that is deprecated in newer versions:

       --use-agent
       --no-use-agent
              This is dummy option. gpg always requires the agent.

I've also it despawning late ron after a while.

My problem is that I only need to fetch/modify keys in a chroot and then want to
exit.
The daemon hanging around prevents me from doing so as it has file handles open
that lets me not remove my bind mount to /dev into the chroot.

I can surely "just kill" the agents, but that seems wrong to me.
Is there any chance to bring back something like the old behaviour "eventually"?
By that I mean that I'm totally fine that it needs an agent and spawns it, but if
--no-use-agent is set (or a better named new argument) the daemon should be
exited immediately.

If there is any way to do that already today, please let me know.
Otherwise what do you think of the suggestion and issue I have - how should I go
on with it?

Details

Version
2.1.15

Event Timeline

cpaelzer added projects: dirmngr, Bug Report.
cpaelzer added a subscriber: cpaelzer.
werner lowered the priority of this task from Normal to Wishlist.Nov 29 2016, 7:01 PM
werner removed a project: Bug Report.
werner added a project: Feature Request.

The agent is not directly involved in keyserver lookups. Instead the dirmngr is
spawned and does this for you. In fact, all network access goes through dirmngr.
However the agent is a mandatory part of gnupg-2 - all private keys are
processed solely by the agent. Thus removing the agent is not an option.
In your case the agent is launched to check whether a private key is available
for an imported public key.

You can stop the agent or the dirmngr using "gpgconf --kill dirmngr"
("gpg-agent"). For your use case a better solution will be to run your script
under the control of the agent (ie. explicily starting the agent):

  GNUPGHOME=$(pwd) gpg-agent --daemon -v MYSCRIPT

This starts the agents and runs MYSCRIPT (/bin/sh is nice for testing). After
MYSCRIPT terminates the agent will be terminated within the next minute.

The reason why your bind mount fails are likely the socket files created there.
I had the same problem with my g13 based disk encryption. The solution to this
are //run/user based sockets. If you create a directory /run/user/UID gnupg
will create a gnupg sub-directory and place the socket files there.

gpg-conf --list-dirs

can be used to check that.

On Tue, Nov 29, 2016 at 7:14 PM, Werner Koch via BTS <gnupg@bugs.g10code.com>
wrote:

[...]
thanks for the clarifications, I was 95% there but that rounds it up to the full
picture.

   GNUPGHOME=$(pwd) gpg-agent --daemon -v MYSCRIPT

This starts the agents and runs MYSCRIPT (/bin/sh is nice for testing). After
MYSCRIPT terminates the agent will be terminated within the next minute.

We more or less do that already, and I can confirm it does "terminate the next
minute".
Unfortunately "the next minute" isn't soon enough for my umount.

So I thought for now I might have to rely on an extra call of "gpgconf --kill
dirmngr" to be sure. But I have found that this doesn't end it for me - maybe
related to our custom GNUPGHOME?
It doesn't seem to stop as intended via gpgconf: (neither with nor without
GNUPGHOME):

$ ps axlf | egrep 'gpg|dirmngr'
1 0 18021 1 20 0 176840 6236 - Ssl ? 0:00 dirmngr --
daemon --homedir /tmp/tmped9zl1ip
$ gpgconf --kill dirmngr
$ ps axlf | egrep 'gpg|dirmngr'
1 0 18021 1 20 0 176840 6236 - Ssl ? 0:00 dirmngr --
daemon --homedir /tmp/tmped9zl1ip
$ GNUPGHOME="/tmp/tmped9zl1ip" gpgconf --kill dirmngr
$ ps axlf | egrep 'gpg|dirmngr'
1 0 18021 1 20 0 176840 6236 -
(Also did the same as root without effect, but avoid filling this report only
with logs)

The more obvious but less graceful "sudo killall dirmngr |:" cleans it up.

The reason why your bind mount fails are likely the socket files created there.

via lsof I only found the following to be related (the /dev bind umount is what
fails).
dirmngr 6771 root 1r CHR LG,0x80000 1,9 0t0
11 /tmp/tmptmucmfm0/target/dev/urandom
dirmngr 6771 root 2w CHR W,LG 1,3 0t0
6 /tmp/tmptmucmfm0/target/dev/null
gpg-agent 6776 root 0r CHR LG 1,3 0t0
6 /tmp/tmptmucmfm0/target/dev/null
gpg-agent 6776 root 1w CHR W,LG 1,3 0t0
6 /tmp/tmptmucmfm0/target/dev/null
gpg-agent 6776 root 2w CHR W,LG 1,3 0t0
6 /tmp/tmptmucmfm0/target/dev/null

Not sure, but I'd not expect these are the sockets.
My assumption would be the open /dev/urandom - especially as I found that I only
need to get rid of dirmngr to proceed.

The solution to this are //run/user based sockets. If you create a directory
/run/user/UID gnupg will create a gnupg sub-directory and place the socket
files there.

gpg-conf --list-dirs

can be used to check that.

I created a log based on that check and lsof (the view from inside the chroot):
gpgconf --list-dirs
lsof +fg /dev
gpgconf --kill dirmngr
lsof +fg /dev
pkill gpg-agent
pkill dirmngr
lsof +fg /dev

I'll attach the full log with this post.
You can find there that the agent and dirmngr do not go away on the gpgconf --
kill.
The socket path OTOH looks ok with "agent-socket:/root/.gnupg/S.gpg-agent"

I added this as first command in chroot to give it a try at least:
$ mkdir -p /run/user/$(id -u)
It "worked" in the sense that the dirs changed e.g. from:
dirmngr-socket:/root/.gnupg/S.dirmngr
to
dirmngr-socket:/run/user/0/gnupg/S.dirmngr
But as I expected that did not change the behavior of blocking to umount the /dev

I really think it is not the sockets but e.g. the /dev/urandom it keeps open.

Is there any way to get the agent&dirmngr from "away next minute" to be "away
before exiting the calling command"?

BTW - I wondered if it would be enough if gpg-agent can stay and to only kill
dirmngr - but it seems I need both gone to let me umount.

If you are on Linux you may simply remove the socket files and the daemons will
terminate.

On Wed, Nov 30, 2016 at 10:28 AM, Werner Koch via BTS <
gnupg@bugs.g10code.com> wrote:

If you are on Linux you may simply remove the socket files and the daemons
will
terminate.

I'm on Linux, but removing the sockets did not kill it for me.

$ ps axlf | grep gpg-agent
1 1000 17332 1 20 0 94340 656 - Ss ? 0:00
gpg-agent --homedir /home/paelzer/.gnupg --use-standard-socket --daemon
$ gpgconf --list-dirs | grep agent
agent-socket:/home/paelzer/.gnupg/S.gpg-agent
$ rm /home/paelzer/.gnupg/S.gpg-agent
$ ps axlf | grep gpg-agent
1 1000 17332 1 20 0 94340 656 - Ss ? 0:00
gpg-agent --homedir /home/paelzer/.gnupg --use-standard-socket --daemon

killall works "great" and I augmented it by some extra protection using
--younger-than and some extra checks.
I'm good on the "kill it as a workaround" side of things.

I think I look more into discussing some sort of "end daemon we just
started after processing, before exiting the program" option.
That way before and after there would be no daemons around and things would
work as expected.
I'd be totally ok if that would not be the default but e.g. could be
controlled by an environment variable.

Can you please switch to 2.1.16? We fixed the inotify based socket removal
detection (issue2756).

On Thu, Dec 1, 2016 at 10:33 AM, Werner Koch via BTS <gnupg@bugs.g10code.com

wrote:

Can you please switch to 2.1.16? We fixed the inotify based socket removal
detection (issue2756).

Sure I can - and I did and can conform that the process removal by that
worked - thanks for the hint.

$ gpg --version
gpg (GnuPG) 2.1.16
libgcrypt 1.7.3-beta
$ gpg --keyserver hkp://keyserver.ubuntu.com:80/ --recv
04450970750A7228C042CD4442C3EB37B6832E30
[...]
$ ps axlf | egrep 'dirmngr|gpg-agent'
1 0 24762 1 20 0 129012 7020 poll_s Ss ? 0:00
dirmngr --daemon --homedir /root/.gnupg
1 0 24766 1 20 0 89924 444 poll_s Ss ? 0:00
gpg-agent --homedir /root/.gnupg --use-standard-socket --daemon
$ rm /root/.gnupg/S.dirmngr
$ ps axlf | egrep 'dirmngr|gpg-agent'
1 0 24766 1 20 0 89924 444 poll_s Ss ? 0:00
gpg-agent --homedir /root/.gnupg --use-standard-socket --daemon
$ rm /root/.gnupg/S.gpg-agent
root@debian-sid:~# ps axlf | egrep 'dirmngr|gpg-agent'
[both gone now]

But OTOH that only gives me a somewhat softer alternative to the "kill" I
use as workaround to remove them explicitly.

In fact I'd have expected that --no-use-agent if used today would have to
throw a fatal error (since it has to use an agent these days).
That way every "consumer" of gpg that used --no-use-agent before (and he
likely did for a reason) would realize "Oh I might have to adapt here".

I'd envision the --no-use-agent these days to at least work as a
" --agent-not-staying-around-after-exit" or something like that.

marcus claimed this task.
marcus added a subscriber: marcus.

Sufficient workarounds have been found.