Skip to content

Memory-Leak in pcscd #174

@Max-Mustermann33

Description

@Max-Mustermann33

Describe the bug
After updating to current versions of pcscd, ccid and libusb I encountered a steady memory leak. In my case the leak was in the range of 10-40 MB each day.

The actual problem stems from the fact that pcscd is calling libusb_init() with the default libusb-context, while ccid is calling libusb_init() with a special context. While this is not illegal to do (afaik) with newer libusb-versions it causes that memory allocated in libusb-function usbi_add_event_source() will not be freed for the libusb_context that was created first. At some point libusb was changed that the memory allocated there will not be freed in usbi_remove_event_source(), but later on when either the libusb_context is destroyed (which never happens in my case) or when an event occurs. But events only occur on the second libusb_context and never on the first one.

I applied this patch to ccid and the memory leak disappeared. Though I guess this would cause trouble when libusb <= 1.0.8 would be used.

The auto-formating here seems to clash with +/- from diff so I had to add some "escape slashes".

diff --git a/src/ccid_usb.c b/src/ccid_usb.c
index 17f1296..573019d 100644
--- a/src/ccid_usb.c
+++ b/src/ccid_usb.c
@@ -59,8 +59,9 @@
 
 /* Using the default libusb context */
 /* does not work for libusb <= 1.0.8 */
-/* #define ctx NULL */
-static libusb_context *ctx = NULL;
+#define ctx NULL
+/*static libusb_context *ctx = NULL;*/
 
 #define CCID_INTERRUPT_SIZE 8
 
@@ -193,9 +194,6 @@ static void close_libusb_if_needed(void)
 {
        bool to_exit = true;
 
-      if (NULL == ctx)
-      return;
-
        /* if at least 1 reader is still in use we do not exit libusb */
        for (int i=0; i<CCID_DRIVER_MAX_READERS; i++)
        {
@@ -207,7 +205,6 @@ static void close_libusb_if_needed(void)
        {
                DEBUG_INFO1("libusb_exit");
                libusb_exit(ctx);
-              ctx = NULL;
        }
 } /* close_libusb_if_needed */
 
@@ -350,15 +347,12 @@ status_t OpenUSBByName(unsigned int reader_index, /*@null@*/ char *device)
        GET_KEY("ifdProductString", values)
        GET_KEY("Copyright", values)
 
-       if (NULL == ctx)
+       rv = libusb_init(ctx);
+       if (rv != 0)
        {
-               rv = libusb_init(&ctx);
-               if (rv != 0)
-               {
-                       DEBUG_CRITICAL2("libusb_init failed: %s", libusb_error_name(rv));
-                       return_value = STATUS_UNSUCCESSFUL;
-                       goto end1;
-               }
+               DEBUG_CRITICAL2("libusb_init failed: %s", libusb_error_name(rv));
+               return_value = STATUS_UNSUCCESSFUL;
+               goto end1;
        }
 
#define GET_KEYS(key, values) \

To Reproduce
pcscd is started with the following arguments:
-S --error --foreground -c

Versions:

  • ccid version 1.6.2 (but should be the same with current master)
  • pcsc-lite version 2.3.3
  • libusb version 1.0.29
  • pcscd -v
    pcsc-lite version 2.2.0
    Copyright (C) 1999-2002 by David Corcoran corcoran@musclecard.com.
    Copyright (C) 2001-2024 by Ludovic Rousseau ludovic.rousseau@free.fr.
    Copyright (C) 2003-2004 by Damien Sauveron sauveron@labri.fr.
    Report bugs to pcsclite-muscle@lists.infradead.org.
    Enabled features: Linux x86_64-pc-linux-gnu serial usb libusb usbdropdir=/usr/lib/pcsc/drivers ipcdir=/var/run filter configdir=//etc/reader.conf.d
    MAX_READERNAME: 128, PCSCLITE_MAX_READERS_CONTEXTS: 16

Platform:

  • Custom OS
  • Does not actually require a smartcard (The problem also exists with softtokens being used)

Log:
The only syslog-message produces by pcscd is the following, but I guess this might just be because it was too early after boot to try and access USB. The daemon still works after that.

pcscd: hotplug_libusb.c:470:HPEstablishUSBNotifications() libusb_init failed: LIBUSB_ERROR_OTHER

Metadata

Metadata

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions