When a user logs in via gdm on a FIPS-enabled system, gnome keyring daemon gets stuck in an infinite loop, which prevents successful login.
Tested with gkd 3.20.0 and libgcrypt 1.8.1.
Here's what happens:
libgcrypt gets initialized by gkd's egg_libgcrypt_initialize().
_gcry_rndlinux_gather_random opens /dev/random and stores the file descriptor to a static variable fd_random.
To become a daemon, gnome keyring performs a double fork and later does a descriptor cleanup in redirect_fds_after_fork(), which reopens /dev/null over descriptors 0-2.
Descriptor 2 before gkd's redirect_fds_after_fork():
# ls -l /proc/10049/fd/2 lr-x------ 1 test users 64 19. říj 17.38 /proc/10049/fd/2 -> /dev/random
After:
# ls -l /proc/10049/fd/2 lr-x------ 1 test users 64 19. říj 17.38 /proc/10049/fd/2 -> /dev/null
libgcrypt however still believes that descriptor 2 points to the random device, so when _gcry_rndlinux_gather_random() is invoked again, it repeatedly read()s 0 byte blocks from the descriptor, creating an infinite loop.
This bug manifests itself only in FIPS mode, because DRBG gets fully seeded on initialization, whereas CSPRNG doesn't do a full initialization, so _gcry_rndlinux_gather_random doesn't get called before the descriptors are cleared.
I reported this also against gnome-keyring, because it looks it should rather be fixed on the gnome-keyring side.