Page MenuHome GnuPG

scdaemon grabs card exclusively; it'd be nice if it didn't
Closed, ResolvedPublic

Description

I have a smartcard device (Yubikey 4) that has both OpenPGP and PIV applications
on it. While scdaemon has claimed the card and is enabling my use of its OpenPGP
app, I cannot use, e.g. jarsigner with the PIV app on the card, which is really
quite sad.

I don't know of any way to bend an application that expects PC/SC to use scdaemon
instead, so I believe it would be beneficial for scdaemon to not lock the card
exclusively, or perhaps only lock it exclusively during key operations, if that's
necessary.

Event Timeline

gniibe added a subscriber: gniibe.

Scdaemon grabs the device after its first use; it gets information on the
card/token and it operates (sign/decrypt) based on those information. If it
releases the device, it should get the info.
Current design of scdaemon is state-full: it caches the information on the card
so that operations can be soon done.
more state-less design could be possible, with the cost of each operation will
be heavy (by getting information each time).

I don't know the PIV app of Yubikey, but, in most cases, such an app can be
written stopping scdaemon beforehand (by a line of gpgconf --reload scdaemon, if
it's a script). It's a simple workaround for now.

Yeah, at the moment I shoot scdaemon with SIGTERM whenever I need to use the PIV
app, which is rare, and have carefully avoided any kind of automated invocation
of the smartcard through scdaemon (e.g. my statusbar polls via ykinfo directly,
rather than invoking gpg --card-status.)

I know essentially nothing about smart cards or PC/SC's design, but what goes
wrong holding the card open shared rather than exclusively? Can other shared
lock holders do drastic things like insert or remove keys, causing scdaemon's
cache to become stale? I would have (naively) guessed that shared holders could
only do things like cryptographic operations which won't pose an issue to
scdaemon's cache. (Admittedly, cryptography is not side-effect free; counters
get incremented, random numbers get generated, but none of that is the kind of
thing that scdaemon caches, right?)

Thanks for thinking about this. :)

I could argue that caching the information about the card and reusing it is pointless and dangerous if such cache is not invalidated when the card is removed. Next time the information is needed, there may be a different card lying on the NFC reader. And it certainly does not make sense to keep the card reserved for exclusive use when the card is physically long gone.

Answering @nwf, I use scdaemon patched to open the card in shared mode, and I do not see any ill effects from that.

But perhaps a right approach would be to release the card and invalidate the cache when:

  1. scdaemon gets notification (directly or from pcscd) that the card is removed, and
  2. after configurable timeout (about a minute or two might be a reasonable default).

Thanks for listening :)

Thank you for your comment.
FYI, when card is removed, scdaemon invalidates cache. So, #1 is already done.
In 2.1.x, scdaemon releases the reader when it finds the card is removed.
(Not for 2.0)

Thank you @gniibe, I will check if scdaemon from 2.1 solves my troubles and followup if it does not.

I can confirm that scdaemon built from today's master (2.1.21-beta73) releases the card, and works as is for my use case.
Version that is included with zesty (2.1.15-1ubuntu7) still keeps the card reserved indefinitely, like all previous versions.

@gniibe , I was happily running scdaemon 2.1.21-beta73 for more than a month and it properly relinquished the card every time. However, a few days ago it got hold of the card and would not let go (or at least, other users of the card got "sharing violation" error from pcscd). I collected some debugging information:

crosser@pccross:~$ /usr/lib/gnupg/scdaemon --version
scdaemon (GnuPG) 2.1.21-beta73
libgcrypt 1.7.6-beta
libksba 1.3.5-unknown
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later https://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

3869 ? SLl 0:00 scdaemon --multi-server

crosser@pccross:~$ ls -l /proc/3869
total 0
dr-xr-xr-x 2 crosser crosser 0 Jun 1 09:01 attr
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 autogroup
-r-------- 1 crosser crosser 0 Jun 1 09:01 auxv
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 cgroup
--w------- 1 crosser crosser 0 Jun 1 09:01 clear_refs
-r--r--r-- 1 crosser crosser 0 Jun 1 08:59 cmdline
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 comm
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 coredump_filter
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 cpuset
lrwxrwxrwx 1 crosser crosser 0 Jun 1 09:01 cwd -> /
-r-------- 1 crosser crosser 0 Jun 1 09:01 environ
lrwxrwxrwx 1 crosser crosser 0 Jun 1 09:01 exe -> /usr/lib/gnupg/scdaemon
dr-x------ 2 crosser crosser 0 Jun 1 09:01 fd
dr-x------ 2 crosser crosser 0 Jun 1 09:01 fdinfo
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 gid_map
-r-------- 1 crosser crosser 0 Jun 1 09:01 io
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 limits
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 loginuid
dr-x------ 2 crosser crosser 0 Jun 1 09:01 map_files
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 maps
-rw------- 1 crosser crosser 0 Jun 1 09:01 mem
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 mountinfo
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 mounts
-r-------- 1 crosser crosser 0 Jun 1 09:01 mountstats
dr-xr-xr-x 5 crosser crosser 0 Jun 1 09:01 net
dr-x--x--x 2 crosser crosser 0 Jun 1 09:01 ns
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 numa_maps
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 oom_adj
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 oom_score
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 oom_score_adj
-r-------- 1 crosser crosser 0 Jun 1 09:01 pagemap
-r-------- 1 crosser crosser 0 Jun 1 09:01 personality
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 projid_map
lrwxrwxrwx 1 crosser crosser 0 Jun 1 09:01 root -> /
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 sched
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 schedstat
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 sessionid
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 setgroups
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 smaps
-r-------- 1 crosser crosser 0 Jun 1 09:01 stack
-r--r--r-- 1 crosser crosser 0 Jun 1 08:59 stat
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 statm
-r--r--r-- 1 crosser crosser 0 Jun 1 08:59 status
-r-------- 1 crosser crosser 0 Jun 1 09:01 syscall
dr-xr-xr-x 4 crosser crosser 0 Jun 1 09:01 task
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 timers
-rw-rw-rw- 1 crosser crosser 0 Jun 1 09:01 timerslack_ns
-rw-r--r-- 1 crosser crosser 0 Jun 1 09:01 uid_map
-r--r--r-- 1 crosser crosser 0 Jun 1 09:01 wchan

commit 36c4e540f1a4992675ee6e0acca1231325457079
Author: NIIBE Yutaka <gniibe@fsij.org>
Date: Fri Apr 14 12:54:06 2017 +0900

agent: Clean up error initialize/return.

* agent/call-pinentry.c (start_pinentry): Return RC.
* agent/command-ssh.c (ssh_handler_request_identities): Don't set ERR.
* agent/findkey.c (try_unprotect_cb): Return ERR.
(unprotect): Don't set RC.
* agent/gpg-agent.c (handle_connections): Don't set fd.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>

root@pccross:/var/tmp# gdb -p 3869 /usr/lib/gnupg/scdaemon
GNU gdb (Ubuntu 7.12.50.20170314-0ubuntu1) 7.12.50.20170314-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/.
Find the GDB manual and other documentation resources online at:
http://www.gnu.org/software/gdb/documentation/.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/lib/gnupg/scdaemon...done.
Attaching to program: /usr/lib/gnupg/scdaemon, process 3869
[New LWP 3870]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007ff49934aa06 in futex_abstimed_wait_cancelable (private=0, abstime=0x0,

expected=0, futex_word=0x7ff49975f200)
at ../sysdeps/unix/sysv/linux/futex-internal.h:205

205 ../sysdeps/unix/sysv/linux/futex-internal.h: No such file or directory.
(gdb) generate-core-file scdaemon.core
warning: target file /proc/3869/cmdline contained unexpected null characters
Saved corefile scdaemon.core

GnuPG 2.2 and 2.4 now have --pcsc-shared option for a user who can control his action in detail.
So, closing this bug report.