From 659d1096a1f1c55d56f02fb5078bc47bca09a4d6 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 1 Mar 2022 07:49:07 -0500 Subject: [PATCH] import libusbx-1.0.25-2.el9 --- .gitignore | 2 +- .libusbx.metadata | 2 +- ...pt-sysfs-attributes-not-terminated-w.patch | 60 -- ...parsing-of-descriptors-for-multi-con.patch | 61 -- ...efully-handle-buggy-devices-with-a-c.patch | 220 ----- SOURCES/1058.patch | 24 + SOURCES/1067.patch | 786 ++++++++++++++++++ SOURCES/1073.patch | 72 ++ SPECS/libusbx.spec | 25 +- 9 files changed, 904 insertions(+), 348 deletions(-) delete mode 100644 SOURCES/0001-linux_usbfs-Accept-sysfs-attributes-not-terminated-w.patch delete mode 100644 SOURCES/0001-linux_usbfs-Fix-parsing-of-descriptors-for-multi-con.patch delete mode 100644 SOURCES/0002-linux_usbfs-Gracefully-handle-buggy-devices-with-a-c.patch create mode 100644 SOURCES/1058.patch create mode 100644 SOURCES/1067.patch create mode 100644 SOURCES/1073.patch diff --git a/.gitignore b/.gitignore index 810d34b..23bb556 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/libusb-1.0.24.tar.bz2 +SOURCES/libusb-1.0.25.tar.bz2 diff --git a/.libusbx.metadata b/.libusbx.metadata index 4d9b532..85d3e2b 100644 --- a/.libusbx.metadata +++ b/.libusbx.metadata @@ -1 +1 @@ -d8d614b538f7c953b6e3b73f1eea5dc70820a7e2 SOURCES/libusb-1.0.24.tar.bz2 +490c33c303622af9b8bff521e6ed0818c64fa623 SOURCES/libusb-1.0.25.tar.bz2 diff --git a/SOURCES/0001-linux_usbfs-Accept-sysfs-attributes-not-terminated-w.patch b/SOURCES/0001-linux_usbfs-Accept-sysfs-attributes-not-terminated-w.patch deleted file mode 100644 index 822fbe0..0000000 --- a/SOURCES/0001-linux_usbfs-Accept-sysfs-attributes-not-terminated-w.patch +++ /dev/null @@ -1,60 +0,0 @@ -From c486d01297a366aae8dcd3f715d0bfd8b995949b Mon Sep 17 00:00:00 2001 -From: Chris Dickens -Date: Mon, 8 Feb 2021 09:27:20 -0800 -Subject: [PATCH 1/2] linux_usbfs: Accept sysfs attributes not terminated with - newline - -Benjamin Berg reports that some CI systems that simulate sysfs devices -are causing libusb to report errors because such systems are not -conforming to the sysfs pattern of terminating attribute values with a -newline character. Reduce the severity of encountering such -non-conforming attibute values from an error that prevents enumeration -to a warning message. - -Closes #857 - -Signed-off-by: Chris Dickens ---- - libusb/os/linux_usbfs.c | 12 +++++++----- - libusb/version_nano.h | 2 +- - 2 files changed, 8 insertions(+), 6 deletions(-) - -diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c -index 4882c0f..ebf8cfe 100644 ---- a/libusb/os/linux_usbfs.c -+++ b/libusb/os/linux_usbfs.c -@@ -505,7 +505,7 @@ static int read_sysfs_attr(struct libusb_context *ctx, - if (fd < 0) - return fd; - -- r = read(fd, buf, sizeof(buf)); -+ r = read(fd, buf, sizeof(buf) - 1); - if (r < 0) { - r = errno; - close(fd); -@@ -523,16 +523,18 @@ static int read_sysfs_attr(struct libusb_context *ctx, - return 0; - } - -- /* The kernel does *not* NULL-terminate the string, but every attribute -+ /* The kernel does *not* NUL-terminate the string, but every attribute - * should be terminated with a newline character. */ - if (!isdigit(buf[0])) { - usbi_err(ctx, "attribute %s doesn't have numeric value?", attr); - return LIBUSB_ERROR_IO; - } else if (buf[r - 1] != '\n') { -- usbi_err(ctx, "attribute %s doesn't end with newline?", attr); -- return LIBUSB_ERROR_IO; -+ usbi_warn(ctx, "attribute %s doesn't end with newline?", attr); -+ } else { -+ /* Remove the terminating newline character */ -+ r--; - } -- buf[r - 1] = '\0'; -+ buf[r] = '\0'; - - errno = 0; - value = strtol(buf, &endptr, 10); --- -2.29.2 - diff --git a/SOURCES/0001-linux_usbfs-Fix-parsing-of-descriptors-for-multi-con.patch b/SOURCES/0001-linux_usbfs-Fix-parsing-of-descriptors-for-multi-con.patch deleted file mode 100644 index 1908bf4..0000000 --- a/SOURCES/0001-linux_usbfs-Fix-parsing-of-descriptors-for-multi-con.patch +++ /dev/null @@ -1,61 +0,0 @@ -From f6d2cb561402c3b6d3627c0eb89e009b503d9067 Mon Sep 17 00:00:00 2001 -From: Chris Dickens -Date: Sun, 13 Dec 2020 15:49:19 -0800 -Subject: [PATCH] linux_usbfs: Fix parsing of descriptors for - multi-configuration devices - -Commit e2be556bd2 ("linux_usbfs: Parse config descriptors during device -initialization") introduced a regression for devices with multiple -configurations. The logic that verifies the reported length of the -configuration descriptors failed to count the length of the -configuration descriptor itself and would truncate the actual length by -9 bytes, leading to a parsing error for subsequent descriptors. - -Closes #825 - -Signed-off-by: Chris Dickens ---- - libusb/os/linux_usbfs.c | 12 ++++++++---- - libusb/version_nano.h | 2 +- - 2 files changed, 9 insertions(+), 5 deletions(-) - -diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c -index fb2ed53..4d2dc8d 100644 ---- a/libusb/os/linux_usbfs.c -+++ b/libusb/os/linux_usbfs.c -@@ -641,7 +641,12 @@ static int seek_to_next_config(struct libusb_context *ctx, - uint8_t *buffer, size_t len) - { - struct usbi_descriptor_header *header; -- int offset = 0; -+ int offset; -+ -+ /* Start seeking past the config descriptor */ -+ offset = LIBUSB_DT_CONFIG_SIZE; -+ buffer += LIBUSB_DT_CONFIG_SIZE; -+ len -= LIBUSB_DT_CONFIG_SIZE; - - while (len > 0) { - if (len < 2) { -@@ -718,7 +723,7 @@ static int parse_config_descriptors(struct libusb_device *dev) - } - - if (priv->sysfs_dir) { -- /* -+ /* - * In sysfs wTotalLength is ignored, instead the kernel returns a - * config descriptor with verified bLength fields, with descriptors - * with an invalid bLength removed. -@@ -727,8 +732,7 @@ static int parse_config_descriptors(struct libusb_device *dev) - int offset; - - if (num_configs > 1 && idx < num_configs - 1) { -- offset = seek_to_next_config(ctx, buffer + LIBUSB_DT_CONFIG_SIZE, -- remaining - LIBUSB_DT_CONFIG_SIZE); -+ offset = seek_to_next_config(ctx, buffer, remaining); - if (offset < 0) - return offset; - sysfs_config_len = (uint16_t)offset; --- -2.29.2 - diff --git a/SOURCES/0002-linux_usbfs-Gracefully-handle-buggy-devices-with-a-c.patch b/SOURCES/0002-linux_usbfs-Gracefully-handle-buggy-devices-with-a-c.patch deleted file mode 100644 index b95a501..0000000 --- a/SOURCES/0002-linux_usbfs-Gracefully-handle-buggy-devices-with-a-c.patch +++ /dev/null @@ -1,220 +0,0 @@ -From f38f09da98acc63966b65b72029b1f7f81166bef Mon Sep 17 00:00:00 2001 -From: Chris Dickens -Date: Mon, 8 Feb 2021 11:56:13 -0800 -Subject: [PATCH 2/2] linux_usbfs: Gracefully handle buggy devices with a - configuration 0 - -The USB spec states that a configuration value of 0 is reserved and is -used to indicate the device in not configured (e.g. is in the address -state). Unfortunately some devices do exist that violate this and use 0 -as the bConfigurationValue of the configuration descriptor. - -Improve how the Linux backend handles such non-conformant devices by -adding special handling around the configuration value 0. Most devices -will not require this special handling, but for those that do there is -no way to distinguish between the device being unconfigured and using -configuration 0. - -Closes #850 - -Signed-off-by: Chris Dickens ---- - libusb/os/linux_usbfs.c | 94 ++++++++++++++++++++++++++--------------- - libusb/version_nano.h | 2 +- - 2 files changed, 60 insertions(+), 36 deletions(-) - -diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c -index ebf8cfe..3a1894c 100644 ---- a/libusb/os/linux_usbfs.c -+++ b/libusb/os/linux_usbfs.c -@@ -128,7 +128,7 @@ struct linux_device_priv { - void *descriptors; - size_t descriptors_len; - struct config_descriptor *config_descriptors; -- uint8_t active_config; /* cache val for !sysfs_available */ -+ int active_config; /* cache val for !sysfs_available */ - }; - - struct linux_device_handle_priv { -@@ -169,6 +169,21 @@ struct linux_transfer_priv { - int iso_packet_offset; - }; - -+static int dev_has_config0(struct libusb_device *dev) -+{ -+ struct linux_device_priv *priv = usbi_get_device_priv(dev); -+ struct config_descriptor *config; -+ uint8_t idx; -+ -+ for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) { -+ config = &priv->config_descriptors[idx]; -+ if (config->desc->bConfigurationValue == 0) -+ return 1; -+ } -+ -+ return 0; -+} -+ - static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) - { - struct libusb_context *ctx = DEVICE_CTX(dev); -@@ -574,22 +589,12 @@ static int sysfs_scan_device(struct libusb_context *ctx, const char *devname) - } - - /* read the bConfigurationValue for a device */ --static int sysfs_get_active_config(struct libusb_device *dev, uint8_t *config) -+static int sysfs_get_active_config(struct libusb_device *dev, int *config) - { - struct linux_device_priv *priv = usbi_get_device_priv(dev); -- int ret, tmp; -- -- ret = read_sysfs_attr(DEVICE_CTX(dev), priv->sysfs_dir, "bConfigurationValue", -- UINT8_MAX, &tmp); -- if (ret < 0) -- return ret; - -- if (tmp == -1) -- tmp = 0; /* unconfigured */ -- -- *config = (uint8_t)tmp; -- -- return 0; -+ return read_sysfs_attr(DEVICE_CTX(dev), priv->sysfs_dir, "bConfigurationValue", -+ UINT8_MAX, config); - } - - int linux_get_device_address(struct libusb_context *ctx, int detached, -@@ -765,6 +770,9 @@ static int parse_config_descriptors(struct libusb_device *dev) - } - } - -+ if (config_desc->bConfigurationValue == 0) -+ usbi_warn(ctx, "device has configuration 0"); -+ - priv->config_descriptors[idx].desc = config_desc; - priv->config_descriptors[idx].actual_len = config_len; - -@@ -798,7 +806,7 @@ static int op_get_active_config_descriptor(struct libusb_device *dev, - { - struct linux_device_priv *priv = usbi_get_device_priv(dev); - void *config_desc; -- uint8_t active_config; -+ int active_config; - int r; - - if (priv->sysfs_dir) { -@@ -810,12 +818,12 @@ static int op_get_active_config_descriptor(struct libusb_device *dev, - active_config = priv->active_config; - } - -- if (active_config == 0) { -+ if (active_config == -1) { - usbi_err(DEVICE_CTX(dev), "device unconfigured"); - return LIBUSB_ERROR_NOT_FOUND; - } - -- r = op_get_config_descriptor_by_value(dev, active_config, &config_desc); -+ r = op_get_config_descriptor_by_value(dev, (uint8_t)active_config, &config_desc); - if (r < 0) - return r; - -@@ -863,17 +871,26 @@ static int usbfs_get_active_config(struct libusb_device *dev, int fd) - - /* we hit this error path frequently with buggy devices :( */ - usbi_warn(DEVICE_CTX(dev), "get configuration failed, errno=%d", errno); -+ -+ /* assume the current configuration is the first one if we have -+ * the configuration descriptors, otherwise treat the device -+ * as unconfigured. */ -+ if (priv->config_descriptors) -+ priv->active_config = (int)priv->config_descriptors[0].desc->bConfigurationValue; -+ else -+ priv->active_config = -1; - } else if (active_config == 0) { -- /* some buggy devices have a configuration 0, but we're -- * reaching into the corner of a corner case here, so let's -- * not support buggy devices in these circumstances. -- * stick to the specs: a configuration value of 0 means -- * unconfigured. */ -- usbi_warn(DEVICE_CTX(dev), "active cfg 0? assuming unconfigured device"); -+ if (dev_has_config0(dev)) { -+ /* some buggy devices have a configuration 0, but we're -+ * reaching into the corner of a corner case here. */ -+ priv->active_config = 0; -+ } else { -+ priv->active_config = -1; -+ } -+ } else { -+ priv->active_config = (int)active_config; - } - -- priv->active_config = active_config; -- - return LIBUSB_SUCCESS; - } - -@@ -1004,9 +1021,9 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, - usbi_warn(ctx, "Missing rw usbfs access; cannot determine " - "active configuration descriptor"); - if (priv->config_descriptors) -- priv->active_config = priv->config_descriptors[0].desc->bConfigurationValue; -+ priv->active_config = (int)priv->config_descriptors[0].desc->bConfigurationValue; - else -- priv->active_config = 0; /* No config dt */ -+ priv->active_config = -1; /* No config dt */ - - return LIBUSB_SUCCESS; - } -@@ -1428,22 +1445,27 @@ static int op_get_configuration(struct libusb_device_handle *handle, - uint8_t *config) - { - struct linux_device_priv *priv = usbi_get_device_priv(handle->dev); -+ int active_config; - int r; - - if (priv->sysfs_dir) { -- r = sysfs_get_active_config(handle->dev, config); -+ r = sysfs_get_active_config(handle->dev, &active_config); - } else { - struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle); - - r = usbfs_get_active_config(handle->dev, hpriv->fd); - if (r == LIBUSB_SUCCESS) -- *config = priv->active_config; -+ active_config = priv->active_config; - } - if (r < 0) - return r; - -- if (*config == 0) -- usbi_err(HANDLE_CTX(handle), "device unconfigured"); -+ if (active_config == -1) { -+ usbi_warn(HANDLE_CTX(handle), "device unconfigured"); -+ active_config = 0; -+ } -+ -+ *config = (uint8_t)active_config; - - return 0; - } -@@ -1467,11 +1489,13 @@ static int op_set_configuration(struct libusb_device_handle *handle, int config) - return LIBUSB_ERROR_OTHER; - } - -- if (config == -1) -- config = 0; -+ /* if necessary, update our cached active config descriptor */ -+ if (!priv->sysfs_dir) { -+ if (config == 0 && !dev_has_config0(handle->dev)) -+ config = -1; - -- /* update our cached active config descriptor */ -- priv->active_config = (uint8_t)config; -+ priv->active_config = config; -+ } - - return LIBUSB_SUCCESS; - } --- -2.29.2 - diff --git a/SOURCES/1058.patch b/SOURCES/1058.patch new file mode 100644 index 0000000..d504455 --- /dev/null +++ b/SOURCES/1058.patch @@ -0,0 +1,24 @@ +From 2529a3fc4f987f93e0774af865ac7cb6557bd0c2 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Fri, 4 Feb 2022 22:50:28 +0100 +Subject: [PATCH] core: Unset device ctx if it has been destroyed + +Devices can outlive their context in some cases (in particular with +python garbage collection). Guard against this happening by clearing the +ctx pointer so that it is not pointing to uninitialized memory. +--- + libusb/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libusb/core.c b/libusb/core.c +index 7893ac23..1c1ada14 100644 +--- a/libusb/core.c ++++ b/libusb/core.c +@@ -2441,6 +2441,7 @@ void API_EXPORTED libusb_exit(libusb_context *ctx) + for_each_device(_ctx, dev) { + usbi_warn(_ctx, "device %d.%d still referenced", + dev->bus_number, dev->device_address); ++ DEVICE_CTX(dev) = NULL; + } + + if (!list_empty(&_ctx->open_devs)) diff --git a/SOURCES/1067.patch b/SOURCES/1067.patch new file mode 100644 index 0000000..81a1333 --- /dev/null +++ b/SOURCES/1067.patch @@ -0,0 +1,786 @@ +From 8420de903a99fb6bfae22a21b2636858f2212baa Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Thu, 15 Jul 2021 17:07:09 +0200 +Subject: [PATCH 01/17] examples: Fix warning about uninitlised variable + +--- + examples/fxload.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/examples/fxload.c b/examples/fxload.c +index 541c3d3a3..85df69952 100644 +--- a/examples/fxload.c ++++ b/examples/fxload.c +@@ -87,7 +87,8 @@ int main(int argc, char*argv[]) + const char *type = NULL; + const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES; + const char *ext, *img_name[] = IMG_TYPE_NAMES; +- int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)]; ++ int fx_type = FX_TYPE_UNDEFINED; ++ int img_type[ARRAYSIZE(path)] = { IMG_TYPE_UNDEFINED, IMG_TYPE_UNDEFINED }; + int opt, status; + unsigned int i, j; + unsigned vid = 0, pid = 0; + +From 23dcbd0521c56fb7543c4f8f73a2a1a4de69aa5e Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Thu, 15 Jul 2021 17:08:12 +0200 +Subject: [PATCH 02/17] core: Add non-null annotations to avoid static analyser + warnings + +It is only valid to call these inline functions with non-null values. +However, static analysis may complain that the functions may dereference +the pointer incorrectly if it is only looking at the function itself +rather than including the surrounding code. + +Add the appropriate annotiations to both fix warnings and improve +detection of bugs in API users. +--- + libusb/libusb.h | 13 +++++++++++++ + libusb/libusbi.h | 14 ++++++++++---- + 2 files changed, 23 insertions(+), 4 deletions(-) + +diff --git a/libusb/libusb.h b/libusb/libusb.h +index 61cacc95a..ea09fa8d9 100644 +--- a/libusb/libusb.h ++++ b/libusb/libusb.h +@@ -77,8 +77,10 @@ typedef SSIZE_T ssize_t; + + #if defined(__GNUC__) + #define LIBUSB_PACKED __attribute__ ((packed)) ++#define LIBUSB_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) + #else + #define LIBUSB_PACKED ++#define LIBUSB_NONNULL(...) + #endif /* __GNUC__ */ + + /** \def LIBUSB_CALL +@@ -1479,6 +1481,7 @@ int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( + * \param transfer a transfer + * \returns pointer to the first byte of the data section + */ ++LIBUSB_NONNULL(1) + static inline unsigned char *libusb_control_transfer_get_data( + struct libusb_transfer *transfer) + { +@@ -1497,6 +1500,7 @@ static inline unsigned char *libusb_control_transfer_get_data( + * \param transfer a transfer + * \returns a casted pointer to the start of the transfer data buffer + */ ++LIBUSB_NONNULL(1) + static inline struct libusb_control_setup *libusb_control_transfer_get_setup( + struct libusb_transfer *transfer) + { +@@ -1526,6 +1530,7 @@ static inline struct libusb_control_setup *libusb_control_transfer_get_setup( + * \ref libusb_control_setup::wLength "wLength" field of + * \ref libusb_control_setup + */ ++LIBUSB_NONNULL(1) + static inline void libusb_fill_control_setup(unsigned char *buffer, + uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + uint16_t wLength) +@@ -1575,6 +1580,7 @@ uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ ++LIBUSB_NONNULL(1) + static inline void libusb_fill_control_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, +@@ -1606,6 +1612,7 @@ static inline void libusb_fill_control_transfer( + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ ++LIBUSB_NONNULL(1) + static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, libusb_transfer_cb_fn callback, +@@ -1637,6 +1644,7 @@ static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ ++LIBUSB_NONNULL(1) + static inline void libusb_fill_bulk_stream_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, uint32_t stream_id, +@@ -1662,6 +1670,7 @@ static inline void libusb_fill_bulk_stream_transfer( + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ ++LIBUSB_NONNULL(1) + static inline void libusb_fill_interrupt_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *buffer, int length, +@@ -1691,6 +1700,7 @@ static inline void libusb_fill_interrupt_transfer( + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ ++LIBUSB_NONNULL(1) + static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, int num_iso_packets, +@@ -1715,6 +1725,7 @@ static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, + * \param length the length to set in each isochronous packet descriptor + * \see libusb_get_max_packet_size() + */ ++LIBUSB_NONNULL(1) + static inline void libusb_set_iso_packet_lengths( + struct libusb_transfer *transfer, unsigned int length) + { +@@ -1740,6 +1751,7 @@ static inline void libusb_set_iso_packet_lengths( + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer_simple() + */ ++LIBUSB_NONNULL(1) + static inline unsigned char *libusb_get_iso_packet_buffer( + struct libusb_transfer *transfer, unsigned int packet) + { +@@ -1782,6 +1794,7 @@ static inline unsigned char *libusb_get_iso_packet_buffer( + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer() + */ ++LIBUSB_NONNULL(1) + static inline unsigned char *libusb_get_iso_packet_buffer_simple( + struct libusb_transfer *transfer, unsigned int packet) + { +diff --git a/libusb/libusbi.h b/libusb/libusbi.h +index 158a9af58..6c924e548 100644 +--- a/libusb/libusbi.h ++++ b/libusb/libusbi.h +@@ -192,11 +192,13 @@ struct list_head { + + #define list_empty(entry) ((entry)->next == (entry)) + ++LIBUSB_NONNULL(1) + static inline void list_init(struct list_head *entry) + { + entry->prev = entry->next = entry; + } + ++LIBUSB_NONNULL(1, 2) + static inline void list_add(struct list_head *entry, struct list_head *head) + { + entry->next = head->next; +@@ -206,6 +208,7 @@ static inline void list_add(struct list_head *entry, struct list_head *head) + head->next = entry; + } + ++LIBUSB_NONNULL(1, 2) + static inline void list_add_tail(struct list_head *entry, + struct list_head *head) + { +@@ -216,6 +219,7 @@ static inline void list_add_tail(struct list_head *entry, + head->prev = entry; + } + ++LIBUSB_NONNULL(1) + static inline void list_del(struct list_head *entry) + { + entry->next->prev = entry->prev; +@@ -223,6 +227,7 @@ static inline void list_del(struct list_head *entry) + entry->next = entry->prev = NULL; + } + ++LIBUSB_NONNULL(1, 2) + static inline void list_cut(struct list_head *list, struct list_head *head) + { + if (list_empty(head)) { +@@ -755,10 +760,10 @@ struct usbi_hotplug_message { + + /* shared data and functions */ + +-void usbi_hotplug_init(struct libusb_context *ctx); +-void usbi_hotplug_exit(struct libusb_context *ctx); ++void usbi_hotplug_init(struct libusb_context *ctx) LIBUSB_NONNULL(1); ++void usbi_hotplug_exit(struct libusb_context *ctx) LIBUSB_NONNULL(1); + void usbi_hotplug_notification(struct libusb_context *ctx, struct libusb_device *dev, +- libusb_hotplug_event event); ++ libusb_hotplug_event event) LIBUSB_NONNULL(1); + void usbi_hotplug_process(struct libusb_context *ctx, struct list_head *hotplug_msgs); + + int usbi_io_init(struct libusb_context *ctx); +@@ -789,7 +794,8 @@ struct usbi_event_source { + + int usbi_add_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle, + short poll_events); +-void usbi_remove_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle); ++void usbi_remove_event_source(struct libusb_context *ctx, usbi_os_handle_t os_handle) ++ LIBUSB_NONNULL(1); + + struct usbi_option { + int is_set; + +From ac527ddcb72e6cd43f2e9d6ae973e9352856dcaf Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:21:09 +0100 +Subject: [PATCH 03/17] core: Silence dereference warnings using assertions in + list_del + +It is guaranteed that entry->next and entry->prev are non-null for a +list item that is part of a list. The static analyser might be confused +though, so add an appropriate assert in case debug mode is enabled. +--- + libusb/libusbi.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libusb/libusbi.h b/libusb/libusbi.h +index 6c924e548..faf6b5daf 100644 +--- a/libusb/libusbi.h ++++ b/libusb/libusbi.h +@@ -222,6 +222,10 @@ static inline void list_add_tail(struct list_head *entry, + LIBUSB_NONNULL(1) + static inline void list_del(struct list_head *entry) + { ++#ifndef NDEBUG ++ assert(entry->next && entry->prev); ++#endif ++ + entry->next->prev = entry->prev; + entry->prev->next = entry->next; + entry->next = entry->prev = NULL; + +From f04d419c0e936333816c969605c2915d5592c328 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Thu, 15 Jul 2021 17:11:41 +0200 +Subject: [PATCH 04/17] core: Fix incorrect free if reallocating to zero size + +A realloc to a size of 0 is equivalent to a free call. As such, in that +case free'ing the original pointer would result in a double free. Fix +this by adding a check that the new size if larger than zero. +--- + libusb/libusbi.h | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/libusb/libusbi.h b/libusb/libusbi.h +index faf6b5daf..652d545ac 100644 +--- a/libusb/libusbi.h ++++ b/libusb/libusbi.h +@@ -257,7 +257,14 @@ static inline void list_splice_front(struct list_head *list, struct list_head *h + + static inline void *usbi_reallocf(void *ptr, size_t size) + { +- void *ret = realloc(ptr, size); ++ void *ret; ++ ++ if (size == 0) { ++ free(ptr); ++ return NULL; ++ } ++ ++ ret = realloc(ptr, size); + + if (!ret) + free(ptr); + +From 883b04fe516adb93a6a1df6c2b4b26e9a4de32be Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Thu, 15 Jul 2021 17:13:18 +0200 +Subject: [PATCH 05/17] linux_usbfs: Work around static analyser thinking fd is + leaked + +Static analysis using coverity is detecting the file descriptor handle +potentially being leaked in some situations. The code itself is actually +sound, but coverity is not correctly following the fact that fd can be +compared against wrapped_fd. + +Fix this by introducing an fd_close variable which is compared to a +fixed value to decide whether to close the fd. Also switch to a goto +pattern rather than returning from different places. +--- + libusb/os/linux_usbfs.c | 51 ++++++++++++++++++++++++----------------- + 1 file changed, 30 insertions(+), 21 deletions(-) + +diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c +index c3006753d..fe6319ee9 100644 +--- a/libusb/os/linux_usbfs.c ++++ b/libusb/os/linux_usbfs.c +@@ -904,7 +904,8 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, + struct linux_device_priv *priv = usbi_get_device_priv(dev); + struct libusb_context *ctx = DEVICE_CTX(dev); + size_t alloc_len; +- int fd, speed, r; ++ int fd, fd_close = -1; ++ int speed, r; + ssize_t nb; + + dev->bus_number = busnum; +@@ -934,19 +935,22 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, + + /* cache descriptors in memory */ + if (sysfs_dir) { +- fd = open_sysfs_attr(ctx, sysfs_dir, "descriptors"); ++ fd = fd_close = open_sysfs_attr(ctx, sysfs_dir, "descriptors"); + } else if (wrapped_fd < 0) { +- fd = get_usbfs_fd(dev, O_RDONLY, 0); ++ fd = fd_close = get_usbfs_fd(dev, O_RDONLY, 0); + } else { + fd = wrapped_fd; + r = lseek(fd, 0, SEEK_SET); + if (r < 0) { + usbi_err(ctx, "lseek failed, errno=%d", errno); +- return LIBUSB_ERROR_IO; ++ r = LIBUSB_ERROR_IO; ++ goto out; + } + } +- if (fd < 0) +- return fd; ++ if (fd < 0) { ++ r = fd; ++ goto out; ++ } + + alloc_len = 0; + do { +@@ -956,9 +960,8 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, + alloc_len += desc_read_length; + priv->descriptors = usbi_reallocf(priv->descriptors, alloc_len); + if (!priv->descriptors) { +- if (fd != wrapped_fd) +- close(fd); +- return LIBUSB_ERROR_NO_MEM; ++ r = LIBUSB_ERROR_NO_MEM; ++ goto out; + } + read_ptr = (uint8_t *)priv->descriptors + priv->descriptors_len; + /* usbfs has holes in the file */ +@@ -967,36 +970,39 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, + nb = read(fd, read_ptr, desc_read_length); + if (nb < 0) { + usbi_err(ctx, "read descriptor failed, errno=%d", errno); +- if (fd != wrapped_fd) +- close(fd); +- return LIBUSB_ERROR_IO; ++ r = LIBUSB_ERROR_IO; ++ goto out; + } + priv->descriptors_len += (size_t)nb; + } while (priv->descriptors_len == alloc_len); + +- if (fd != wrapped_fd) +- close(fd); ++ if (fd_close >= 0) { ++ close(fd_close); ++ fd_close = -1; ++ } + + if (priv->descriptors_len < LIBUSB_DT_DEVICE_SIZE) { + usbi_err(ctx, "short descriptor read (%zu)", priv->descriptors_len); +- return LIBUSB_ERROR_IO; ++ r = LIBUSB_ERROR_IO; ++ goto out; + } + + r = parse_config_descriptors(dev); + if (r < 0) +- return r; ++ goto out; + + memcpy(&dev->device_descriptor, priv->descriptors, LIBUSB_DT_DEVICE_SIZE); + + if (sysfs_dir) { + /* sysfs descriptors are in bus-endian format */ + usbi_localize_device_descriptor(&dev->device_descriptor); +- return LIBUSB_SUCCESS; ++ r = LIBUSB_SUCCESS; ++ goto out; + } + + /* cache active config */ + if (wrapped_fd < 0) +- fd = get_usbfs_fd(dev, O_RDWR, 1); ++ fd = fd_close = get_usbfs_fd(dev, O_RDWR, 1); + else + fd = wrapped_fd; + if (fd < 0) { +@@ -1009,12 +1015,15 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum, + else + priv->active_config = -1; /* No config dt */ + +- return LIBUSB_SUCCESS; ++ r = LIBUSB_SUCCESS; ++ goto out; + } + + r = usbfs_get_active_config(dev, fd); +- if (fd != wrapped_fd) +- close(fd); ++ ++out: ++ if (fd_close >= 0) ++ close(fd_close); + + return r; + } + +From 06f4523117ffbe77fbc370a403cc274016867139 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:08:31 +0100 +Subject: [PATCH 06/17] examples: Fix warning about NULL pointer dereference + +It seems like coverity is getting confused by the transfers being global +variables, thinking that img_transfer may become NULL again. + +Fix this bogus warning by moving the check down. +--- + examples/dpfp.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/examples/dpfp.c b/examples/dpfp.c +index 682865053..4a871ee4f 100644 +--- a/examples/dpfp.c ++++ b/examples/dpfp.c +@@ -554,13 +554,8 @@ static int do_init(void) + static int alloc_transfers(void) + { + img_transfer = libusb_alloc_transfer(0); +- if (!img_transfer) { +- errno = ENOMEM; +- return -1; +- } +- + irq_transfer = libusb_alloc_transfer(0); +- if (!irq_transfer) { ++ if (!img_transfer || !irq_transfer) { + errno = ENOMEM; + return -1; + } + +From b2a2163b3893e57d839b5247072fcb2fdfd5d4e4 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:09:53 +0100 +Subject: [PATCH 07/17] examples: Assert the data fits into our static buffer + +--- + examples/ezusb.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/examples/ezusb.c b/examples/ezusb.c +index 4bed12a4c..0ea787190 100644 +--- a/examples/ezusb.c ++++ b/examples/ezusb.c +@@ -23,6 +23,7 @@ + + #include + ++#include + #include + #include + #include +@@ -303,6 +304,7 @@ static int parse_ihex(FILE *image, void *context, + buf[3] = 0; + len = strtoul(buf+1, NULL, 16); + buf[3] = tmp; ++ assert(len <= sizeof(data)); + + /* Read the target offset (address up to 64KB) */ + tmp = buf[7]; + +From 13fbb9923e4ee5b6d9dfa13396e1faf5da13a2af Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:11:28 +0100 +Subject: [PATCH 08/17] core: Tell coverity that libusb_open does not free + +Internally, libusb_open does an unref in an error case. coverity doesn't +seem to notice that this is balanced with the earlier ref, and thinks +that the passed in device may be free'ed. Annotate the function to +prevent misdetections. + +An alternative would be to only take the reference after checking for +the error, but the code is idiomatic as-is. +--- + libusb/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libusb/core.c b/libusb/core.c +index 7893ac238..076c2bbbd 100644 +--- a/libusb/core.c ++++ b/libusb/core.c +@@ -1293,6 +1293,7 @@ int API_EXPORTED libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, + * \returns LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + * \returns another LIBUSB_ERROR code on other failure + */ ++/* coverity[-free: arg-0] false positive due to error handling path */ + int API_EXPORTED libusb_open(libusb_device *dev, + libusb_device_handle **dev_handle) + { + +From 1d576b41cfe229cbf98a3fc9aeb819562cccaaae Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:13:26 +0100 +Subject: [PATCH 09/17] core: Remove unneeded bounds check + +This makes the code slightly less efficient, but shuts up warnings that +the later switch ends up with dead error handling code. +--- + libusb/core.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/libusb/core.c b/libusb/core.c +index 076c2bbbd..73fb6524a 100644 +--- a/libusb/core.c ++++ b/libusb/core.c +@@ -2201,10 +2201,6 @@ int API_EXPORTED libusb_set_option(libusb_context *ctx, + return r; + } + +- if (option >= LIBUSB_OPTION_MAX) { +- return LIBUSB_ERROR_INVALID_PARAM; +- } +- + if (NULL == ctx) { + usbi_mutex_static_lock(&default_context_lock); + default_context_options[option].is_set = 1; + +From ca3e801e2f54308651a180e48e2381b5ed88eef1 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:15:16 +0100 +Subject: [PATCH 10/17] descriptor: Avoid uninitialized memory warnings + +The static analyzer has trouble understanding that get_config_descriptor +fills in the config descriptor. Just initializing the memory silences +the warning and is safe to do. +--- + libusb/descriptor.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libusb/descriptor.c b/libusb/descriptor.c +index 253ef1c31..dbcf061d9 100644 +--- a/libusb/descriptor.c ++++ b/libusb/descriptor.c +@@ -555,7 +555,7 @@ int API_EXPORTED libusb_get_device_descriptor(libusb_device *dev, + int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev, + struct libusb_config_descriptor **config) + { +- union usbi_config_desc_buf _config; ++ union usbi_config_desc_buf _config = { 0, }; + uint16_t config_len; + uint8_t *buf; + int r; +@@ -658,7 +658,7 @@ int API_EXPORTED libusb_get_config_descriptor_by_value(libusb_device *dev, + + usbi_dbg(DEVICE_CTX(dev), "value %u", bConfigurationValue); + for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) { +- union usbi_config_desc_buf _config; ++ union usbi_config_desc_buf _config = { 0, }; + + r = get_config_descriptor(dev, idx, _config.buf, sizeof(_config.buf)); + if (r < 0) + +From e7a0c0d507d662ad3661f52286452880ef75f488 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:19:04 +0100 +Subject: [PATCH 11/17] io: Suppress invalid free warning from coverity + +Coverity is not understanding the pointer arithmetic involved with the +transfer in-memory storage. As such, it flags the free as invalid, even +though everything is fine. Add an appropriate comment to silence the +warning. +--- + libusb/io.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/libusb/io.c b/libusb/io.c +index 0d2ac9ea2..d32cdc1bf 100644 +--- a/libusb/io.c ++++ b/libusb/io.c +@@ -1691,8 +1691,10 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, + transfer->callback(transfer); + /* transfer might have been freed by the above call, do not use from + * this point. */ +- if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) ++ if (flags & LIBUSB_TRANSFER_FREE_TRANSFER) { ++ /* coverity[incorrect_free] is reported incorrectly here due to the memory layout */ + libusb_free_transfer(transfer); ++ } + libusb_unref_device(dev_handle->dev); + return r; + } + +From fc44484ef782bdb05880a26c502a7ea33c0eb72f Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:20:27 +0100 +Subject: [PATCH 12/17] io: Suppress missing unlock warning from coverity + +The function is supposed to take the lock, as such, this is the expected +behaviour. +--- + libusb/io.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libusb/io.c b/libusb/io.c +index d32cdc1bf..96bd22861 100644 +--- a/libusb/io.c ++++ b/libusb/io.c +@@ -1786,6 +1786,7 @@ int API_EXPORTED libusb_try_lock_events(libusb_context *ctx) + return 1; + + ctx->event_handler_active = 1; ++ /* coverity[missing_unlock] is expected here */ + return 0; + } + + +From c97e4bb846f41a112262df668e9d8e449555f295 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:23:45 +0100 +Subject: [PATCH 13/17] events_posix: Silence warnings about zero-allocated + memory + +The static analyser got confused by the fact that fds may be NULL if +there are no event sources. Obviously, in that case the later loop that +dereferences fds will never do anything, but coverity seems to miss that +part. + +Silence the warning by doing an early return from the function. +--- + libusb/os/events_posix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libusb/os/events_posix.c b/libusb/os/events_posix.c +index 715a2d551..172f8afe8 100644 +--- a/libusb/os/events_posix.c ++++ b/libusb/os/events_posix.c +@@ -201,6 +201,10 @@ int usbi_alloc_event_data(struct libusb_context *ctx) + for_each_event_source(ctx, ievent_source) + ctx->event_data_cnt++; + ++ /* Silence warning about use of zero allocated memory. */ ++ if (ctx->event_data_cnt == 0) ++ return 0; ++ + fds = calloc(ctx->event_data_cnt, sizeof(*fds)); + if (!fds) + return LIBUSB_ERROR_NO_MEM; + +From 7e9919314f82c61df6950390412ab3b80c84b707 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:25:40 +0100 +Subject: [PATCH 14/17] linux_usbfs: Disable sleep workaround when using udev + +The workaround to sleep 10ms if a device node has not yet been created +is definitely not needed with udev. I am not sure what the race looks +like in the netlink case, unless some other userspace daemon (udev) is +reacting to the same message and creates the device. + +I suppose, in the long run this might be fixed by removing the netlink +code. +--- + libusb/os/linux_usbfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c +index fe6319ee9..b4837895d 100644 +--- a/libusb/os/linux_usbfs.c ++++ b/libusb/os/linux_usbfs.c +@@ -197,6 +197,8 @@ static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) + if (fd != -1) + return fd; /* Success */ + ++/* This workaround is only relevant when watching netlink directly rather than udev. */ ++#if !defined(HAVE_LIBUDEV) + if (errno == ENOENT) { + const long delay_ms = 10L; + const struct timespec delay_ts = { 0L, delay_ms * 1000L * 1000L }; +@@ -211,6 +213,7 @@ static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) + if (fd != -1) + return fd; /* Success */ + } ++#endif + + if (!silent) { + usbi_err(ctx, "libusb couldn't open USB device %s, errno=%d", path, errno); + +From 126aacee12b49ed525534a81ad830db692654ba0 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:29:35 +0100 +Subject: [PATCH 15/17] linux_usbfs: Silence coverity warnings about returned + offset + +The seek_to_next_config function returns an offset. This was marked as +tained by coverity, but really, we can trust it to be OK in the +surrounding code. Mark the return value to silence the warnings. +--- + libusb/os/linux_usbfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c +index b4837895d..ba55913f0 100644 +--- a/libusb/os/linux_usbfs.c ++++ b/libusb/os/linux_usbfs.c +@@ -638,6 +638,7 @@ int linux_get_device_address(struct libusb_context *ctx, int detached, + } + + /* Return offset of the next config descriptor */ ++/* coverity[-taint_source] as the returned offset can be trusted */ + static int seek_to_next_config(struct libusb_context *ctx, + uint8_t *buffer, size_t len) + { + +From 42679d2d8573dfc27b9c78f832749728997a516b Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Wed, 9 Feb 2022 19:31:44 +0100 +Subject: [PATCH 16/17] linux_usbfs: Silence coverity warning about missing + locking + +The reap_status field is locked in most cases when it is accessed. +This causes a warning from coverity, however locking is not needed in +this particular case as the transfer has not yet been submitted. + +As such, add an appropriate comment to silence the warning. +--- + libusb/os/linux_usbfs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c +index ba55913f0..2e65d66ce 100644 +--- a/libusb/os/linux_usbfs.c ++++ b/libusb/os/linux_usbfs.c +@@ -1984,6 +1984,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) + tpriv->num_urbs = num_urbs; + tpriv->num_retired = 0; + tpriv->reap_action = NORMAL; ++ /* coverity[missing_lock] as we don't need to lock before submission */ + tpriv->reap_status = LIBUSB_TRANSFER_COMPLETED; + + for (i = 0; i < num_urbs; i++) { + +From 38cff7a438f7a00d76aa03cc1c35f6be395c167d Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Thu, 10 Feb 2022 10:51:11 +0100 +Subject: [PATCH 17/17] core: Silence coverity by handling long log messages in + one statement + +Having two statements seems to confuse coverity. Having two checks right +after each other doesn't give us anything, so just fold them into one so +that the static analyzer is not getting confused. +--- + libusb/core.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/libusb/core.c b/libusb/core.c +index 73fb6524a..03adcb758 100644 +--- a/libusb/core.c ++++ b/libusb/core.c +@@ -2629,16 +2629,13 @@ static void log_v(struct libusb_context *ctx, enum libusb_log_level level, + header_len = 0; + } + +- text_len = vsnprintf(buf + header_len, sizeof(buf) - (size_t)header_len, ++ text_len = vsnprintf(buf + header_len, ++ sizeof(buf) - (size_t)header_len - (int)sizeof(USBI_LOG_LINE_END), + format, args); +- if (text_len < 0 || text_len + header_len >= (int)sizeof(buf)) { ++ if (text_len < 0 || text_len + header_len + (int)sizeof(USBI_LOG_LINE_END) >= (int)sizeof(buf)) { + /* Truncated log output. On some platforms a -1 return value means +- * that the output was truncated. */ +- text_len = (int)sizeof(buf) - header_len; +- } +- if (header_len + text_len + (int)sizeof(USBI_LOG_LINE_END) >= (int)sizeof(buf)) { +- /* Need to truncate the text slightly to fit on the terminator. */ +- text_len -= (header_len + text_len + (int)sizeof(USBI_LOG_LINE_END)) - (int)sizeof(buf); ++ * that the output was truncated (e.g. glibc < 2.1). */ ++ text_len = (int)sizeof(buf) - header_len - (int)sizeof(USBI_LOG_LINE_END); + } + strcpy(buf + header_len + text_len, USBI_LOG_LINE_END); + diff --git a/SOURCES/1073.patch b/SOURCES/1073.patch new file mode 100644 index 0000000..8b91a48 --- /dev/null +++ b/SOURCES/1073.patch @@ -0,0 +1,72 @@ +From bf833ee6adf58bd4a4a468aa729cdc78bdc13ede Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Tue, 15 Feb 2022 11:13:41 +0100 +Subject: [PATCH 1/2] core: Catch NULL dev_handle when getting a transfer's + context + +The dev_handle will be set to NULL when the transfer is still in-flight +while the device is closed. In that case, the transfer free function +will try to access the context and would run into a NULL pointer +dereference. + +Add a test for dev_handle being valid before dereferencing it further. +--- + libusb/libusbi.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libusb/libusbi.h b/libusb/libusbi.h +index 158a9af5..dde43df2 100644 +--- a/libusb/libusbi.h ++++ b/libusb/libusbi.h +@@ -330,7 +330,7 @@ void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, + + #define DEVICE_CTX(dev) ((dev)->ctx) + #define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) +-#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) ++#define TRANSFER_CTX(transfer) ((transfer)->dev_handle ? HANDLE_CTX((transfer)->dev_handle) : NULL) + #define ITRANSFER_CTX(itransfer) \ + (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer))) + + +From 6428090ea77dfb80906a146977ea7fd6de4718c8 Mon Sep 17 00:00:00 2001 +From: Benjamin Berg +Date: Tue, 15 Feb 2022 10:59:00 +0100 +Subject: [PATCH 2/2] io: Unset dev_handle when removing transfer from flying + list + +API users might hold on to transfers a bit longer than they are in the +flying list. If they then close the device prior to freeing all +transfers, we would end up with invalid pointers to the device. + +Fix this by setting the device handle to NULL when removing the device +from the flying list. This matches the behaviour when the device is +closed while the transfer is still in the flying list. + +Specifically, the libgusb wrapper will currently only free the +underlying transfer in a later mainloop iteration (as a side effect on +how GTask does memory management). It is possible to fix this, but it +would make memory management within libgusb much more error prone. +--- + libusb/io.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libusb/io.c b/libusb/io.c +index 0d2ac9ea..4e6d8984 100644 +--- a/libusb/io.c ++++ b/libusb/io.c +@@ -1456,6 +1456,7 @@ static int add_to_flying_list(struct usbi_transfer *itransfer) + * if it fails to update the timer for the next timeout. */ + static int remove_from_flying_list(struct usbi_transfer *itransfer) + { ++ struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + struct libusb_context *ctx = ITRANSFER_CTX(itransfer); + int rearm_timer; + int r = 0; +@@ -1466,6 +1467,7 @@ static int remove_from_flying_list(struct usbi_transfer *itransfer) + list_del(&itransfer->list); + if (rearm_timer) + r = arm_timer_for_next_timeout(ctx); ++ transfer->dev_handle = NULL; + usbi_mutex_unlock(&ctx->flying_transfers_lock); + + return r; diff --git a/SPECS/libusbx.spec b/SPECS/libusbx.spec index 83e7679..08883a1 100644 --- a/SPECS/libusbx.spec +++ b/SPECS/libusbx.spec @@ -1,7 +1,7 @@ Summary: Library for accessing USB devices Name: libusbx -Version: 1.0.24 -Release: 4%{?dist} +Version: 1.0.25 +Release: 2%{?dist} # upstream libusbx has merged back with libusb and is now called libusb again # but we already have a libusb package for the old libusb-compat-0.1, renaming # that to libusb-compat while at the same time giving this its name is a bit @@ -14,9 +14,14 @@ BuildRequires: make Provides: libusb1 = %{version}-%{release} Obsoletes: libusb1 <= 1.0.9 -Patch001: 0001-linux_usbfs-Accept-sysfs-attributes-not-terminated-w.patch -Patch002: 0001-linux_usbfs-Fix-parsing-of-descriptors-for-multi-con.patch -Patch003: 0002-linux_usbfs-Gracefully-handle-buggy-devices-with-a-c.patch +# Fix a crash after libusb_exit API has been misused +# https://bugzilla.redhat.com/show_bug.cgi?id=2050638 +Patch0001: https://github.com/libusb/libusb/pull/1058.patch +# Fix a crash if a transfer outlives closing the device +Patch0002: https://github.com/libusb/libusb/pull/1073.patch + +# Pull in coverity related fixes +Patch9999: https://github.com/libusb/libusb/pull/1067.patch %description This package provides a way for applications to access USB devices. @@ -123,6 +128,16 @@ LD_LIBRARY_PATH=libusb/.libs $RPM_BUILD_ROOT%{_bindir}/libusb-example-listdevs %changelog +* Tue Feb 15 2022 Benjamin Berg - 1.0.25-2 +- Fix a crash if a transfer outlives closing the device + Related: #1938801 + +* Thu Feb 10 2022 Benjamin Berg - 1.0.25-1 +- Update to 1.0.25 +- Fix a crash after libusb_exit API has been misused +- Add patchset to fix covscan reports + Resolves: #1938801 + * Mon Aug 09 2021 Mohan Boddu - 1.0.24-4 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688