From 436c722bc28ce8b27a5232a0eceb80eb4811e481 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Wed, 30 Nov 2022 21:05:16 +0100 Subject: [PATCH] Update to 0.13.0 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2135760 Signed-off-by: Victor Toso --- .gitignore | 1 + 0001-Revert-remove-usbredirserver.patch | 593 ++++++++++++++++++ ...er-Fix-unserialize-on-pristine-check.patch | 193 ------ ...reset-parser-s-fields-on-unserialize.patch | 63 -- sources | 2 +- usbredir.spec | 12 +- 6 files changed, 603 insertions(+), 261 deletions(-) create mode 100644 0001-Revert-remove-usbredirserver.patch delete mode 100644 0001-usbredirparser-Fix-unserialize-on-pristine-check.patch delete mode 100644 0002-usbredirparser-reset-parser-s-fields-on-unserialize.patch diff --git a/.gitignore b/.gitignore index af8493a..a12549c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ /usbredir-0.7.1.tar.bz2 /usbredir-0.8.0.tar.bz2 /usbredir-0.12.0.tar.xz +/usbredir-0.13.0.tar.xz diff --git a/0001-Revert-remove-usbredirserver.patch b/0001-Revert-remove-usbredirserver.patch new file mode 100644 index 0000000..adb031f --- /dev/null +++ b/0001-Revert-remove-usbredirserver.patch @@ -0,0 +1,593 @@ +From e06a042c1c0eccefeccc63e419b9b09bef11e28f Mon Sep 17 00:00:00 2001 +From: Victor Toso +Date: Wed, 30 Nov 2022 21:02:20 +0100 +Subject: [PATCH] Revert "remove usbredirserver" +Content-type: text/plain + +This reverts commit f4ffdce329305da2803684776f7659083a530819. +--- + README.md | 4 + + meson.build | 1 + + usbredirserver/meson.build | 12 + + usbredirserver/usbredirserver.1 | 41 +++ + usbredirserver/usbredirserver.c | 474 ++++++++++++++++++++++++++++++++ + 5 files changed, 532 insertions(+) + create mode 100644 usbredirserver/meson.build + create mode 100644 usbredirserver/usbredirserver.1 + create mode 100644 usbredirserver/usbredirserver.c + +diff --git a/README.md b/README.md +index ed04cca..2acb7b0 100644 +--- a/README.md ++++ b/README.md +@@ -28,6 +28,10 @@ The usbredirect binary is an usbredir client for exporting an USB device either + as TCP client or server, for use from another (virtual) machine through the + usbredir protocol. + ++## usbredirserver ++ ++A simple tcp server usb-host, using usbredirhost ++ + ## usbredirtestclient + + A small testclient for the usbredir protocol over tcp, using usbredirparser +diff --git a/meson.build b/meson.build +index aac9909..e740778 100644 +--- a/meson.build ++++ b/meson.build +@@ -103,6 +103,7 @@ if get_option('tools').enabled() + subdir('tools') + endif + if host_machine.system() != 'windows' ++ subdir('usbredirserver') + subdir('usbredirtestclient') + + if get_option('fuzzing').enabled() +diff --git a/usbredirserver/meson.build b/usbredirserver/meson.build +new file mode 100644 +index 0000000..de40681 +--- /dev/null ++++ b/usbredirserver/meson.build +@@ -0,0 +1,12 @@ ++usbredirserver_sources = [ ++ 'usbredirserver.c', ++] ++ ++executable('usbredirserver', ++ sources : usbredirserver_sources, ++ c_args : '-Wno-deprecated-declarations', ++ install : true, ++ install_dir: get_option('sbindir'), ++ dependencies : usbredir_host_lib_dep) ++ ++install_man('usbredirserver.1') +diff --git a/usbredirserver/usbredirserver.1 b/usbredirserver/usbredirserver.1 +new file mode 100644 +index 0000000..d5a6793 +--- /dev/null ++++ b/usbredirserver/usbredirserver.1 +@@ -0,0 +1,41 @@ ++.TH USBREDIRSERVER "1" "April 2012" "usbredirserver" "User Commands" ++.SH NAME ++usbredirserver \- exporting an USB device for use from another (virtual) machine ++.SH SYNOPSIS ++.B usbredirserver ++[\fI-p|--port \fR] [\fI-v|--verbose <0-5>\fR] [\fI-4 ] ++\fI\fR ++.SH DESCRIPTION ++usbredirserver is a small standalone server for exporting an USB device for ++use from another (virtual) machine through the usbredir protocol. ++.PP ++You can specify the USB device to export either by USB id in the form of ++\fI:\fR, or by USB bus number and device address in the form ++of \fI-\fR. ++.PP ++Notice that an instance of usbredirserver can only be used to export a ++single USB device. If you want to export multiple devices you can start ++multiple instances listening on different TCP ports. ++.SH OPTIONS ++.TP ++\fB\-p\fR, \fB\-\-port\fR=\fIPORT\fR ++Set the TCP port to listen on to \fIPORT\fR ++.TP ++\fB\-v\fR, \fB\-\-verbose\fR=\fIVERBOSE\fR ++Set usbredirserver's verbosity level to \fIVERBOSE\fR, this mostly affects USB ++redirection related messages. Valid values are 0-5: ++.br ++0:Silent 1:Errors 2:Warnings 3:Info 4:Debug 5:Debug++ ++.SH AUTHOR ++Written by Hans de Goede ++.SH REPORTING BUGS ++You can report bugs to the spice-devel mailinglist: ++http://lists.freedesktop.org/mailman/listinfo/spice-devel ++or filing an issue at: ++https://gitlab.freedesktop.org/spice/usbredir/issues/new ++.SH COPYRIGHT ++Copyright 2010-2012 Red Hat, Inc. ++License GPLv2+: GNU GPL version 2 or later . ++.br ++This is free software: you are free to change and redistribute it. ++There is NO WARRANTY, to the extent permitted by law. +diff --git a/usbredirserver/usbredirserver.c b/usbredirserver/usbredirserver.c +new file mode 100644 +index 0000000..badb7bc +--- /dev/null ++++ b/usbredirserver/usbredirserver.c +@@ -0,0 +1,474 @@ ++/* usbredirserver.c simple usb network redirection tcp/ip server (host). ++ ++ Copyright 2010-2011 Red Hat, Inc. ++ ++ Red Hat Authors: ++ Hans de Goede ++ ++ This program is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this library; if not, see . ++*/ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "usbredirhost.h" ++ ++ ++#define SERVER_VERSION "usbredirserver " PACKAGE_VERSION ++ ++#if !defined(SOL_TCP) && defined(IPPROTO_TCP) ++#define SOL_TCP IPPROTO_TCP ++#endif ++#if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE) && defined(__APPLE__) ++#define TCP_KEEPIDLE TCP_KEEPALIVE ++#endif ++ ++static int verbose = usbredirparser_info; ++static int client_fd, running = 1; ++static libusb_context *ctx; ++static struct usbredirhost *host; ++ ++static const struct option longopts[] = { ++ { "port", required_argument, NULL, 'p' }, ++ { "verbose", required_argument, NULL, 'v' }, ++ { "ipv4", required_argument, NULL, '4' }, ++ { "ipv6", required_argument, NULL, '6' }, ++ { "keepalive", required_argument, NULL, 'k' }, ++ { "help", no_argument, NULL, 'h' }, ++ { NULL, 0, NULL, 0 } ++}; ++ ++static void usbredirserver_log(void *priv, int level, const char *msg) ++{ ++ if (level <= verbose) ++ fprintf(stderr, "%s\n", msg); ++} ++ ++static int usbredirserver_read(void *priv, uint8_t *data, int count) ++{ ++ int r = read(client_fd, data, count); ++ if (r < 0) { ++ if (errno == EAGAIN) ++ return 0; ++ return -1; ++ } ++ if (r == 0) { /* Client disconnected */ ++ close(client_fd); ++ client_fd = -1; ++ } ++ return r; ++} ++ ++static int usbredirserver_write(void *priv, uint8_t *data, int count) ++{ ++ int r = write(client_fd, data, count); ++ if (r < 0) { ++ if (errno == EAGAIN) ++ return 0; ++ if (errno == EPIPE) { /* Client disconnected */ ++ close(client_fd); ++ client_fd = -1; ++ return 0; ++ } ++ return -1; ++ } ++ return r; ++} ++ ++static void usage(int exit_code, char *argv0) ++{ ++ fprintf(exit_code? stderr:stdout, ++ "Usage: %s [-p|--port ] [-v|--verbose <0-5>] " ++ "[[-4|--ipv4 ipaddr]|[-6|--ipv6 ipaddr]] " ++ "[-k|--keepalive seconds] " ++ "\n", ++ argv0); ++ exit(exit_code); ++} ++ ++static void invalid_usb_device_id(char *usb_device_id, char *argv0) ++{ ++ fprintf(stderr, "Invalid usb device identifier: %s\n", usb_device_id); ++ usage(1, argv0); ++} ++ ++static void run_main_loop(void) ++{ ++ const struct libusb_pollfd **pollfds = NULL; ++ fd_set readfds, writefds; ++ int i, n, nfds; ++ struct timeval timeout, *timeout_p; ++ ++ while (running && client_fd != -1) { ++ FD_ZERO(&readfds); ++ FD_ZERO(&writefds); ++ ++ FD_SET(client_fd, &readfds); ++ if (usbredirhost_has_data_to_write(host)) { ++ FD_SET(client_fd, &writefds); ++ } ++ nfds = client_fd + 1; ++ ++ free(pollfds); ++ pollfds = libusb_get_pollfds(ctx); ++ for (i = 0; pollfds && pollfds[i]; i++) { ++ if (pollfds[i]->events & POLLIN) { ++ FD_SET(pollfds[i]->fd, &readfds); ++ } ++ if (pollfds[i]->events & POLLOUT) { ++ FD_SET(pollfds[i]->fd, &writefds); ++ } ++ if (pollfds[i]->fd >= nfds) ++ nfds = pollfds[i]->fd + 1; ++ } ++ ++ if (libusb_get_next_timeout(ctx, &timeout) == 1) { ++ timeout_p = &timeout; ++ } else { ++ timeout_p = NULL; ++ } ++ n = select(nfds, &readfds, &writefds, NULL, timeout_p); ++ if (n == -1) { ++ if (errno == EINTR) { ++ continue; ++ } ++ perror("select"); ++ break; ++ } ++ memset(&timeout, 0, sizeof(timeout)); ++ if (n == 0) { ++ libusb_handle_events_timeout(ctx, &timeout); ++ continue; ++ } ++ ++ if (FD_ISSET(client_fd, &readfds)) { ++ if (usbredirhost_read_guest_data(host)) { ++ break; ++ } ++ } ++ /* usbredirhost_read_guest_data may have detected client disconnect */ ++ if (client_fd == -1) ++ break; ++ ++ if (FD_ISSET(client_fd, &writefds)) { ++ if (usbredirhost_write_guest_data(host)) { ++ break; ++ } ++ } ++ ++ for (i = 0; pollfds && pollfds[i]; i++) { ++ if (FD_ISSET(pollfds[i]->fd, &readfds) || ++ FD_ISSET(pollfds[i]->fd, &writefds)) { ++ libusb_handle_events_timeout(ctx, &timeout); ++ break; ++ } ++ } ++ } ++ if (client_fd != -1) { /* Broken out of the loop because of an error ? */ ++ close(client_fd); ++ client_fd = -1; ++ } ++ free(pollfds); ++} ++ ++static void quit_handler(int sig) ++{ ++ running = 0; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int o, flags, server_fd = -1; ++ char *endptr, *delim; ++ int port = 4000; ++ int usbbus = -1; ++ int usbaddr = -1; ++ int usbvendor = -1; ++ int usbproduct = -1; ++ int on = 1; ++ int keepalive = -1; ++ char *ipv4_addr = NULL, *ipv6_addr = NULL; ++ union { ++ struct sockaddr_in v4; ++ struct sockaddr_in6 v6; ++ } serveraddr; ++ struct sigaction act; ++ libusb_device_handle *handle = NULL; ++ ++ while ((o = getopt_long(argc, argv, "hp:v:4:6:k:", longopts, NULL)) != -1) { ++ switch (o) { ++ case 'p': ++ port = strtol(optarg, &endptr, 10); ++ if (*endptr != '\0') { ++ fprintf(stderr, "Invalid value for --port: '%s'\n", optarg); ++ usage(1, argv[0]); ++ } ++ break; ++ case 'v': ++ verbose = strtol(optarg, &endptr, 10); ++ if (*endptr != '\0') { ++ fprintf(stderr, "Invalid value for --verbose: '%s'\n", optarg); ++ usage(1, argv[0]); ++ } ++ break; ++ case '4': ++ ipv4_addr = optarg; ++ break; ++ case '6': ++ ipv6_addr = optarg; ++ break; ++ case 'k': ++ keepalive = strtol(optarg, &endptr, 10); ++ if (*endptr != '\0') { ++ fprintf(stderr, "Invalid value for -k: '%s'\n", optarg); ++ usage(1, argv[0]); ++ } ++ break; ++ case '?': ++ case 'h': ++ usage(o == '?', argv[0]); ++ break; ++ } ++ } ++ if (optind == argc) { ++ fprintf(stderr, "Missing usb device identifier argument\n"); ++ usage(1, argv[0]); ++ } ++ delim = strchr(argv[optind], '-'); ++ if (delim && delim[1]) { ++ usbbus = strtol(argv[optind], &endptr, 10); ++ if (*endptr != '-') { ++ invalid_usb_device_id(argv[optind], argv[0]); ++ } ++ usbaddr = strtol(delim + 1, &endptr, 10); ++ if (*endptr != '\0') { ++ invalid_usb_device_id(argv[optind], argv[0]); ++ } ++ } else { ++ delim = strchr(argv[optind], ':'); ++ if (!delim || !delim[1]) { ++ invalid_usb_device_id(argv[optind], argv[0]); ++ } ++ usbvendor = strtol(argv[optind], &endptr, 16); ++ if (*endptr != ':' || usbvendor <= 0 || usbvendor > 0xffff) { ++ invalid_usb_device_id(argv[optind], argv[0]); ++ } ++ usbproduct = strtol(delim + 1, &endptr, 16); ++ /* Product ID 0000 is valid */ ++ if (*endptr != '\0' || usbproduct < 0 || usbproduct > 0xffff) { ++ invalid_usb_device_id(argv[optind], argv[0]); ++ } ++ } ++ optind++; ++ if (optind != argc) { ++ fprintf(stderr, "Excess non option arguments\n"); ++ usage(1, argv[0]); ++ } ++ ++ memset(&act, 0, sizeof(act)); ++ act.sa_handler = quit_handler; ++ sigaction(SIGINT, &act, NULL); ++ sigaction(SIGHUP, &act, NULL); ++ sigaction(SIGTERM, &act, NULL); ++ sigaction(SIGQUIT, &act, NULL); ++ ++ if (libusb_init(&ctx)) { ++ fprintf(stderr, "Could not init libusb\n"); ++ exit(1); ++ } ++ ++#if LIBUSB_API_VERSION >= 0x01000106 ++ libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, verbose); ++#else ++ libusb_set_debug(ctx, verbose); ++#endif ++ ++ if (ipv4_addr) { ++ server_fd = socket(AF_INET, SOCK_STREAM, 0); ++ } else { ++ server_fd = socket(AF_INET6, SOCK_STREAM, 0); ++ } ++ if (server_fd == -1) { ++ perror("Error creating ip socket"); ++ exit(1); ++ } ++ ++ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { ++ perror("Error setsockopt(SO_REUSEADDR) failed"); ++ exit(1); ++ } ++ ++ memset(&serveraddr, 0, sizeof(serveraddr)); ++ ++ if (ipv4_addr) { ++ serveraddr.v4.sin_family = AF_INET; ++ serveraddr.v4.sin_port = htons(port); ++ if ((inet_pton(AF_INET, ipv4_addr, ++ &serveraddr.v4.sin_addr)) != 1) { ++ perror("Error convert ipv4 address"); ++ exit(1); ++ } ++ } else { ++ serveraddr.v6.sin6_family = AF_INET6; ++ serveraddr.v6.sin6_port = htons(port); ++ if (ipv6_addr) { ++ if ((inet_pton(AF_INET6, ipv6_addr, ++ &serveraddr.v6.sin6_addr)) != 1) { ++ perror("Error convert ipv6 address"); ++ exit(1); ++ } ++ } else { ++ serveraddr.v6.sin6_addr = in6addr_any; ++ } ++ } ++ ++ if (bind(server_fd, (struct sockaddr *)&serveraddr, ++ sizeof(serveraddr))) { ++ perror("Error bind"); ++ exit(1); ++ } ++ ++ if (listen(server_fd, 1)) { ++ perror("Error listening"); ++ exit(1); ++ } ++ ++ while (running) { ++ client_fd = accept(server_fd, NULL, 0); ++ if (client_fd == -1) { ++ if (errno == EINTR) { ++ continue; ++ } ++ perror("accept"); ++ break; ++ } ++ ++ if (keepalive > 0) { ++ int optval = 1; ++ socklen_t optlen = sizeof(optval); ++ if (setsockopt(client_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) == -1) { ++ if (errno != ENOTSUP) { ++ perror("setsockopt SO_KEEPALIVE error."); ++ break; ++ } ++ } ++ optval = keepalive; /* set default TCP_KEEPIDLE time from cmdline */ ++ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) == -1) { ++ if (errno != ENOTSUP) { ++ perror("setsockopt TCP_KEEPIDLE error."); ++ break; ++ } ++ } ++ optval = 10; /* set default TCP_KEEPINTVL time as 10s */ ++ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) == -1) { ++ if (errno != ENOTSUP) { ++ perror("setsockopt TCP_KEEPINTVL error."); ++ break; ++ } ++ } ++ optval = 3; /* set default TCP_KEEPCNT as 3 */ ++ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPCNT, &optval, optlen) == -1) { ++ if (errno != ENOTSUP) { ++ perror("setsockopt TCP_KEEPCNT error."); ++ break; ++ } ++ } ++ } ++ ++ flags = fcntl(client_fd, F_GETFL); ++ if (flags == -1) { ++ perror("fcntl F_GETFL"); ++ break; ++ } ++ flags = fcntl(client_fd, F_SETFL, flags | O_NONBLOCK); ++ if (flags == -1) { ++ perror("fcntl F_SETFL O_NONBLOCK"); ++ break; ++ } ++ ++ /* Try to find the specified usb device */ ++ if (usbvendor != -1) { ++ handle = libusb_open_device_with_vid_pid(ctx, usbvendor, ++ usbproduct); ++ if (!handle) { ++ fprintf(stderr, ++ "Could not open an usb-device with vid:pid %04x:%04x\n", ++ usbvendor, usbproduct); ++ } else if (verbose >= usbredirparser_info) { ++ libusb_device *dev; ++ dev = libusb_get_device(handle); ++ fprintf(stderr, "Open a usb-device with vid:pid %04x:%04x on " ++ "bus %03x device %03x\n", ++ usbvendor, usbproduct, ++ libusb_get_bus_number(dev), ++ libusb_get_device_address(dev)); ++ } ++ } else { ++ libusb_device **list = NULL; ++ ssize_t i, n; ++ ++ n = libusb_get_device_list(ctx, &list); ++ for (i = 0; i < n; i++) { ++ if (libusb_get_bus_number(list[i]) == usbbus && ++ libusb_get_device_address(list[i]) == usbaddr) ++ break; ++ } ++ if (i < n) { ++ if (libusb_open(list[i], &handle) != 0) { ++ fprintf(stderr, ++ "Could not open usb-device at busnum-devnum %d-%d\n", ++ usbbus, usbaddr); ++ } ++ } else { ++ fprintf(stderr, ++ "Could not find an usb-device at busnum-devnum %d-%d\n", ++ usbbus, usbaddr); ++ } ++ libusb_free_device_list(list, 1); ++ } ++ if (!handle) { ++ close(client_fd); ++ continue; ++ } ++ ++ host = usbredirhost_open(ctx, handle, usbredirserver_log, ++ usbredirserver_read, usbredirserver_write, ++ NULL, SERVER_VERSION, verbose, 0); ++ if (!host) ++ exit(1); ++ run_main_loop(); ++ usbredirhost_close(host); ++ handle = NULL; ++ } ++ ++ close(server_fd); ++ libusb_exit(ctx); ++ exit(0); ++} +-- +2.38.1 + diff --git a/0001-usbredirparser-Fix-unserialize-on-pristine-check.patch b/0001-usbredirparser-Fix-unserialize-on-pristine-check.patch deleted file mode 100644 index 9d21c34..0000000 --- a/0001-usbredirparser-Fix-unserialize-on-pristine-check.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 6bf41a231b445ac5190c32e281b698b1ee5379b4 Mon Sep 17 00:00:00 2001 -From: Victor Toso -Date: Fri, 24 Jun 2022 23:29:08 +0200 -Subject: [PATCH 1/2] usbredirparser: Fix unserialize on pristine check -Content-type: text/plain - -As mentioned in the bug below, the user is trying to migrate QEMU and -it is failing on the unserialization of usbredirparser at the target -host. The user does not have USB attached to the VM at all. - -I've added a test that shows that serialization is currently broken. -It fails at the 'pristine' check in usbredirparser_unserialize(). - -This check was added with e37d86c "Skip empty write buffers when -unserializing parser" and restricted further with 186c4c7 "Avoid -memory leak from ill-formatted serialization data" - -The issue here is that usbredirparser's initialization sets some -fields and thus it isn't guaranteed to be pristine. - -The parser's basic data is: - - | write_buf_count ... : 1 - | write_buf ........ : 0xbc03e0 - | write_buf_total_size: 80 - | data ............. : (nil) - | header_read: ...... : 0 - | type_header_read .. : 0 - | data_read: ........ : 0 - -The current fix is to to ignore write_buf checks as, again, they are -not guaranteed to be pristine. usbredirparser library should properly -overwrite them when unserializing the data and if there were pending -buffers, they should be freed. - -Related: https://bugzilla.redhat.com/show_bug.cgi?id=2096008 - -Signed-off-by: Victor Toso ---- - tests/meson.build | 1 + - tests/serializer.c | 113 ++++++++++++++++++++++++++++++++ - usbredirparser/usbredirparser.c | 4 +- - 3 files changed, 115 insertions(+), 3 deletions(-) - create mode 100644 tests/serializer.c - -diff --git a/tests/meson.build b/tests/meson.build -index 0d4397b..2a179c9 100644 ---- a/tests/meson.build -+++ b/tests/meson.build -@@ -1,5 +1,6 @@ - tests = [ - 'filter', -+ 'serializer', - ] - - deps = dependency('glib-2.0') -diff --git a/tests/serializer.c b/tests/serializer.c -new file mode 100644 -index 0000000..4bd669e ---- /dev/null -+++ b/tests/serializer.c -@@ -0,0 +1,113 @@ -+/* -+ * Copyright 2022 Red Hat, Inc. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, see . -+*/ -+#include "config.h" -+ -+#define G_LOG_DOMAIN "serializer" -+#define G_LOG_USE_STRUCTURED -+ -+#include "usbredirparser.h" -+ -+#include -+#include -+#include -+#include -+ -+ -+static void -+log_cb(void *priv, int level, const char *msg) -+{ -+ GLogLevelFlags glog_level; -+ -+ switch(level) { -+ case usbredirparser_error: -+ glog_level = G_LOG_LEVEL_ERROR; -+ break; -+ case usbredirparser_warning: -+ glog_level = G_LOG_LEVEL_WARNING; -+ break; -+ case usbredirparser_info: -+ glog_level = G_LOG_LEVEL_INFO; -+ break; -+ case usbredirparser_debug: -+ case usbredirparser_debug_data: -+ glog_level = G_LOG_LEVEL_DEBUG; -+ break; -+ default: -+ g_warn_if_reached(); -+ return; -+ } -+ g_log_structured(G_LOG_DOMAIN, glog_level, "MESSAGE", msg); -+} -+ -+static struct usbredirparser * -+get_usbredirparser(void) -+{ -+ struct usbredirparser *parser = usbredirparser_create(); -+ g_assert_nonnull(parser); -+ -+ uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, }; -+ /* Typical caps set by usbredirhost */ -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version); -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_filter); -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_device_disconnect_ack); -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size); -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids); -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_32bits_bulk_length); -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_bulk_receiving); -+#if LIBUSBX_API_VERSION >= 0x01000103 -+ usbredirparser_caps_set_cap(caps, usb_redir_cap_bulk_streams); -+#endif -+ int parser_flags = usbredirparser_fl_usb_host; -+ -+ parser->log_func = log_cb; -+ usbredirparser_init(parser, -+ PACKAGE_STRING, -+ caps, -+ USB_REDIR_CAPS_SIZE, -+ parser_flags); -+ return parser; -+} -+ -+static void -+simple (gconstpointer user_data) -+{ -+ uint8_t *state = NULL; -+ int ret, len = -1; -+ -+ struct usbredirparser *source = get_usbredirparser(); -+ ret = usbredirparser_serialize(source, &state, &len); -+ g_assert_cmpint(ret, ==, 0); -+ -+ struct usbredirparser *target = get_usbredirparser(); -+ ret = usbredirparser_unserialize(target, state, len); -+ g_assert_cmpint(ret, ==, 0); -+ -+ g_clear_pointer(&state, free); -+ usbredirparser_destroy(source); -+ usbredirparser_destroy(target); -+} -+ -+int -+main(int argc, char **argv) -+{ -+ setlocale(LC_ALL, ""); -+ g_test_init(&argc, &argv, NULL); -+ -+ g_test_add_data_func("/serializer/serialize-and-unserialize", NULL, simple); -+ -+ return g_test_run(); -+} -diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c -index cd1136b..a5dd0e7 100644 ---- a/usbredirparser/usbredirparser.c -+++ b/usbredirparser/usbredirparser.c -@@ -1816,9 +1816,7 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub, - return -1; - } - -- if (!(parser->write_buf_count == 0 && parser->write_buf == NULL && -- parser->write_buf_total_size == 0 && -- parser->data == NULL && parser->header_read == 0 && -+ if (!(parser->data == NULL && parser->header_read == 0 && - parser->type_header_read == 0 && parser->data_read == 0)) { - ERROR("unserialization must use a pristine parser"); - usbredirparser_assert_invariants(parser); --- -2.37.1 - diff --git a/0002-usbredirparser-reset-parser-s-fields-on-unserialize.patch b/0002-usbredirparser-reset-parser-s-fields-on-unserialize.patch deleted file mode 100644 index c46aa22..0000000 --- a/0002-usbredirparser-reset-parser-s-fields-on-unserialize.patch +++ /dev/null @@ -1,63 +0,0 @@ -From b93c4cae1aebda786a478677d6364308e4579ade Mon Sep 17 00:00:00 2001 -From: Victor Toso -Date: Sat, 25 Jun 2022 00:29:12 +0200 -Subject: [PATCH 2/2] usbredirparser: reset parser's fields on unserialize -Content-type: text/plain - -This is a followup from previous commit and fixes the following leak. - - | 104 (24 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 15 of 19 - | at 0x484A464: calloc (vg_replace_malloc.c:1328) - | by 0x485A238: usbredirparser_queue (usbredirparser.c:1235) - | by 0x485A571: usbredirparser_init (usbredirparser.c:227) - | by 0x40130B: get_usbredirparser (serializer.c:77) - | by 0x401379: simple (serializer.c:95) - | by 0x48FA3DD: ??? (in /usr/lib64/libglib-2.0.so.0.7200.2) - | by 0x48FA144: ??? (in /usr/lib64/libglib-2.0.so.0.7200.2) - | by 0x48FA8E1: g_test_run_suite (in /usr/lib64/libglib-2.0.so.0.7200.2) - | by 0x48FA94C: g_test_run (in /usr/lib64/libglib-2.0.so.0.7200.2) - | by 0x401161: main (serializer.c:112) - | - | LEAK SUMMARY: - | definitely lost: 24 bytes in 1 blocks - | indirectly lost: 80 bytes in 1 blocks - | possibly lost: 0 bytes in 0 blocks - | still reachable: 25,500 bytes in 17 blocks - | suppressed: 0 bytes in 0 blocks - | Reachable blocks (those to which a pointer was found) are not shown. - | To see them, rerun with: --leak-check=full --show-leak-kinds=all - -Signed-off-by: Victor Toso ---- - usbredirparser/usbredirparser.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c -index a5dd0e7..9bfc27c 100644 ---- a/usbredirparser/usbredirparser.c -+++ b/usbredirparser/usbredirparser.c -@@ -1823,6 +1823,21 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub, - return -1; - } - -+ { -+ /* We need to reset parser's state to receive unserialized -+ * data. */ -+ struct usbredirparser_buf *wbuf = parser->write_buf; -+ while (wbuf) { -+ struct usbredirparser_buf *next_wbuf = wbuf->next; -+ free(wbuf->buf); -+ free(wbuf); -+ wbuf = next_wbuf; -+ } -+ parser->write_buf = NULL; -+ parser->write_buf_count = 0; -+ parser->write_buf_total_size = 0; -+ } -+ - if (unserialize_int(parser, &state, &remain, &i, "length")) { - usbredirparser_assert_invariants(parser); - return -1; --- -2.37.1 - diff --git a/sources b/sources index af70fd0..2457eb5 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (usbredir-0.12.0.tar.xz) = f509a6b5d410fec53efbdc186b80376d6b7f5b34c6c33f2037a83bf105743667c5a18a6d1ef33d6b3c57c1ed6a52b94536369ca768eddb70fda7b436d35fe6ab +SHA512 (usbredir-0.13.0.tar.xz) = dd27b1794233d4a278c3ca0e2a1ef9518946d8c7422cf58bb83d8ed5b4358133da27bdb0f44ad7b679a9983b3c419c3ab014486735614f7ceea85bfa62904273 diff --git a/usbredir.spec b/usbredir.spec index c4969cc..ad7c23f 100644 --- a/usbredir.spec +++ b/usbredir.spec @@ -1,12 +1,11 @@ Name: usbredir -Version: 0.12.0 -Release: 3%{?dist} +Version: 0.13.0 +Release: 1%{?dist} Summary: USB network redirection protocol libraries License: LGPLv2+ URL: https://spice-space.org/usbredir.html Source0: http://spice-space.org/download/%{name}/%{name}-%{version}.tar.xz -Patch0001: 0001-usbredirparser-Fix-unserialize-on-pristine-check.patch -Patch0002: 0002-usbredirparser-reset-parser-s-fields-on-unserialize.patch +Patch0001: 0001-Revert-remove-usbredirserver.patch BuildRequires: gcc BuildRequires: glib2-devel BuildRequires: libusb1-devel >= 1.0.9 @@ -86,6 +85,11 @@ A simple USB host TCP server, using libusbredirhost. %changelog +* Wed Nov 30 2022 Victor Toso - 0.13.0-1 +- Rebase to latest upstream: 0.13.0 +- Keeps usbredirserver binary (removed upstream) + Related: rhbz#2135760 + * Thu Jul 28 2022 Victor Toso - 0.12.0-3 - Fix unserialization (migration regression) Related: rhbz#2111368