File libusb-compat-hide-libusb-1_0.patch of Package libusb-compat (Revision 6996cff2833c14afe10ea482866f2730)
Currently displaying revision 6996cff2833c14afe10ea482866f2730 , Show latest
354
1
https://sourceforge.net/p/libusb/mailman/message/34281276/
2
3
From: Stanislav Brabec <sbrabec@suse.com>
4
Date: Thu, 09 Jul 2015 18:21:56 +0200
5
Subject: [libusb] [PATCH][libusb-compat-0.1][TRY3] Prevent libusb-1.0 library symbol clash
6
List-Id: Development discussion for libusb <libusb-devel.lists.sourceforge.net>
7
8
libusb-1.0 uses functions like libusb_open. These names are generic, and
9
there are applications using libusb-0.1 using these names for its own
10
functions (e. g. scanbuttond). If such applications uses libusb-compat,
11
it crashes due to symbol clash.
12
13
Such clash is easy to fix in Open Source applications, but impossible to
14
fix inside closed source applications.
15
16
Dynamic linker does not allow to hide symbols from dependent library.
17
This could be worked around by loading this library later by dlopen()
18
with RTLD_LOCAL flag.
19
20
Do this on platforms where it can be done.
21
22
This change makes visible only libusb-0.1 symbols but not libusb-1.0
23
symbols.
24
25
(It could be theoretically possible to introduce clashes with libdl, but
26
it is much less probable.)
27
28
To wrap symbols inside static inline functions inside libusb.h, the
29
Makefile generates a modified version if libusb.h.
30
31
How to reproduce:
32
33
Take testlibusb.c from libusb-0.1.12/tests and replace print_device
34
by libusb_open. Without this change the application crashes.
35
36
Reference:
37
https://bugzilla.opensuse.org/show_bug.cgi?id=596411
38
39
Signed-off-by: Stanislav Brabec <sbrabec@suse.com>
40
---
41
configure.ac | 23 +++++++++
42
libusb/Makefile.am | 11 +++-
43
libusb/core.c | 14 ++++++
44
libusb/libusb-dload.h | 124 ++++++++++++++++++++++++++++++++++++++++++++++
45
m4/au_check_lib_soname.m4 | 43 ++++++++++++++++
46
m4/au_have_gnu_errno.m4 | 17 +++++++
47
6 files changed, 231 insertions(+), 1 deletion(-)
48
create mode 100644 libusb/libusb-dload.h
49
create mode 100644 m4/au_check_lib_soname.m4
50
create mode 100644 m4/au_have_gnu_errno.m4
51
52
diff --git a/configure.ac b/configure.ac
53
index debfef2..18a86c2 100644
54
--- a/configure.ac
55
+++ b/configure.ac
56
57
PKG_CHECK_MODULES([LIBUSB_1_0], libusb-1.0 >= 0.9.1)
58
AC_SUBST(LIBUSB_1_0_CFLAGS)
59
AC_SUBST(LIBUSB_1_0_LIBS)
60
+# dlopen wrapper needs a location of libusb.h.
61
+# Setting of LIBUSB_H variable can override pkg-config.
62
+if test x"$LIBUSB_H" = x ; then
63
+ LIBUSB_H=`echo "$LIBUSB_1_0_CFLAGS" | sed 's/^.*-I//;s/ .*//'`/libusb.h
64
+fi
65
+AC_CHECK_FILE([$LIBUSB_H], [
66
+ AC_SUBST([LIBUSB_H])], [
67
+ LIBUSB_H=""])
68
+
69
+# Checks for dynamic loading of libusb-1.0
70
+ac_save_LIBS="$LIBS"
71
+AC_CHECK_HEADER([dlfcn.h], [
72
+ AS_IF([test x"$LIBUSB_H" != x], [
73
+ AC_CHECK_LIB([dl], [dlopen], [
74
+ AC_CHECK_LIB([dl], [dlsym], [
75
+ AU_CHECK_LIB_SONAME([LIBUSB_1_0], [usb-1.0], [libusb_open])])])])])
76
+LIBS="$ac_save_LIBS"
77
+if test x"$LIBUSB_1_0_SONAME" != x ; then
78
+ AC_DEFINE_UNQUOTED([LIBUSB_1_0_SONAME], ["$LIBUSB_1_0_SONAME"], [SONAME of libusb-1.0. If defined, libusb-1.0 can be hidden.])
79
+fi
80
+AM_CONDITIONAL([USE_LIBUSB_1_0_DLOAD], [test x"$LIBUSB_1_0_SONAME" != x])
81
+
82
+AU_HAVE_GNU_ERRNO_H
83
84
# Message logging
85
AC_ARG_ENABLE([log], [AS_HELP_STRING([--disable-log], [disable all logging])],
86
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
87
index 33a609a..39da7c2 100644
88
--- a/libusb/Makefile.am
89
+++ b/libusb/Makefile.am
90
91
include_HEADERS = usb.h
92
lib_LTLIBRARIES = libusb.la
93
94
-libusb_la_SOURCES = core.c usbi.h
95
+libusb_la_SOURCES = core.c usbi.h libusb-dload.h
96
libusb_la_CFLAGS = -fvisibility=hidden $(AM_CFLAGS) $(LIBUSB_1_0_CFLAGS)
97
+if USE_LIBUSB_1_0_DLOAD
98
+libusb_la_LIBADD = -ldl
99
+BUILT_SOURCES = libusb-wrapped.h
100
+else
101
libusb_la_LIBADD = $(LIBUSB_1_0_LIBS)
102
+endif
103
libusb_la_LDFLAGS = -version-info $(LT_MAJOR):$(LT_REVISION):$(LT_AGE) \
104
-release 0.1
105
106
+# Rewrite libusb.h to refer to wrapped calls.
107
+libusb-wrapped.h: $(LIBUSB_H) $(srcdir)/Makefile.am
108
+ $(SED) 's/return libusb_control_transfer/return (dl_libusb_control_transfer)/;s/\tlibusb_transfer_set_stream_id/\t(dl_libusb_transfer_set_stream_id)/;/LIBUSB_CALL libusb/{s/(/)(/;s/LIBUSB_CALL /(*dl_/;}' <$< >$@
109
+CONFIG_CLEAN_FILES = libusb-wrapped.h
110
diff --git a/libusb/core.c b/libusb/core.c
111
index e6e500b..b516f59 100644
112
--- a/libusb/core.c
113
+++ b/libusb/core.c
114
115
#include <stdio.h>
116
#include <string.h>
117
118
+#ifdef LIBUSB_1_0_SONAME
119
+#include "libusb-dload.h"
120
+#else
121
#include <libusb.h>
122
+#endif
123
124
#include "usb.h"
125
#include "usbi.h"
126
127
128
#define compat_err(e) -(errno=libusb_to_errno(e))
129
130
+#ifdef LIBUSB_1_0_SONAME
131
+static void __attribute__ ((constructor)) _usb_init (void)
132
+{
133
+ libusb_dl_init ();
134
+}
135
+#endif
136
+
137
static void __attribute__ ((destructor)) _usb_exit (void)
138
{
139
if (ctx) {
140
libusb_exit (ctx);
141
ctx = NULL;
142
}
143
+#ifdef LIBUSB_1_0_SONAME
144
+ libusb_dl_exit ();
145
+#endif
146
}
147
148
static int libusb_to_errno(int result)
149
diff --git a/libusb/libusb-dload.h b/libusb/libusb-dload.h
150
new file mode 100644
151
index 0000000..a45a7b2
152
--- /dev/null
153
+++ b/libusb/libusb-dload.h
154
155
+/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
156
+/*
157
+ * Dynamic library wrapper hiding library symbols from libusb-1.O
158
+ * Copyright (C) 2015 Stanislav Brabec <sbrabec@suse.com>
159
+ *
160
+ * This library is free software; you can redistribute it and/or
161
+ * modify it under the terms of the GNU Lesser General Public
162
+ * License as published by the Free Software Foundation; either
163
+ * version 2.1 of the License, or (at your option) any later version.
164
+ *
165
+ * This library is distributed in the hope that it will be useful,
166
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
167
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
168
+ * Lesser General Public License for more details.
169
+ *
170
+ * You should have received a copy of the GNU Lesser General Public
171
+ * License along with this library; if not, write to the Free Software
172
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
173
+ */
174
+
175
+#include "config.h"
176
+
177
+/* Include libusb.h with wrapped inlined calls and declarations in style
178
+ * needed for dlopen references */
179
+#include "libusb-wrapped.h"
180
+
181
+/* Now make defines to force use of these wrappers */
182
+#define libusb_bulk_transfer (dl_libusb_bulk_transfer)
183
+#define libusb_claim_interface (dl_libusb_claim_interface)
184
+#define libusb_release_interface (dl_libusb_release_interface)
185
+#define libusb_clear_halt (dl_libusb_clear_halt)
186
+#define libusb_reset_device (dl_libusb_reset_device)
187
+#define libusb_get_bus_number (dl_libusb_get_bus_number)
188
+#define libusb_open (dl_libusb_open)
189
+#define libusb_close (dl_libusb_close)
190
+#define libusb_set_configuration (dl_libusb_set_configuration)
191
+#define libusb_control_transfer (dl_libusb_control_transfer)
192
+#define libusb_detach_kernel_driver (dl_libusb_detach_kernel_driver)
193
+#define libusb_exit (dl_libusb_exit)
194
+#define libusb_set_debug (dl_libusb_set_debug)
195
+#define libusb_free_config_descriptor (dl_libusb_free_config_descriptor)
196
+#define libusb_free_device_list (dl_libusb_free_device_list)
197
+#define libusb_ref_device (dl_libusb_ref_device)
198
+#define libusb_unref_device (dl_libusb_unref_device)
199
+#define libusb_get_config_descriptor (dl_libusb_get_config_descriptor)
200
+#define libusb_free_config_descriptor (dl_libusb_free_config_descriptor)
201
+#define libusb_get_device_address (dl_libusb_get_device_address)
202
+#define libusb_get_device_descriptor (dl_libusb_get_device_descriptor)
203
+#define libusb_get_device_list (dl_libusb_get_device_list)
204
+#define libusb_free_device_list (dl_libusb_free_device_list)
205
+#define libusb_get_string_descriptor_ascii (dl_libusb_get_string_descriptor_ascii)
206
+#define libusb_init (dl_libusb_init)
207
+#define libusb_exit (dl_libusb_exit)
208
+#define libusb_set_debug (dl_libusb_set_debug)
209
+#define libusb_interrupt_transfer (dl_libusb_interrupt_transfer)
210
+#define libusb_kernel_driver_active (dl_libusb_kernel_driver_active)
211
+#define libusb_detach_kernel_driver (dl_libusb_detach_kernel_driver)
212
+#define libusb_ref_device (dl_libusb_ref_device)
213
+#define libusb_unref_device (dl_libusb_unref_device)
214
+#define libusb_release_interface (dl_libusb_release_interface)
215
+#define libusb_reset_device (dl_libusb_reset_device)
216
+#define libusb_set_configuration (dl_libusb_set_configuration)
217
+#define libusb_claim_interface (dl_libusb_claim_interface)
218
+#define libusb_set_debug (dl_libusb_set_debug)
219
+#define libusb_set_interface_alt_setting (dl_libusb_set_interface_alt_setting)
220
+#define libusb_clear_halt (dl_libusb_clear_halt)
221
+#define libusb_unref_device (dl_libusb_unref_device)
222
+
223
+/* And finally handle the wrapping itself */
224
+#include <stdlib.h>
225
+#include <stdio.h>
226
+#include <string.h>
227
+#include <errno.h>
228
+#include <dlfcn.h>
229
+
230
+static void *libusb_dl_handle;
231
+
232
+#define libusb_dl_set_call(call)\
233
+ if (!(dl_##call = dlsym(libusb_dl_handle, #call)))\
234
+ goto failure;
235
+static inline void libusb_dl_init(void) {
236
+ if (!(libusb_dl_handle = dlopen(LIBUSB_1_0_SONAME, RTLD_NOW|RTLD_LOCAL)))
237
+ goto failure;
238
+ libusb_dl_set_call(libusb_bulk_transfer);
239
+ libusb_dl_set_call(libusb_claim_interface);
240
+ libusb_dl_set_call(libusb_clear_halt);
241
+ libusb_dl_set_call(libusb_get_bus_number);
242
+ libusb_dl_set_call(libusb_open);
243
+ libusb_dl_set_call(libusb_close);
244
+ libusb_dl_set_call(libusb_control_transfer);
245
+ libusb_dl_set_call(libusb_detach_kernel_driver);
246
+ libusb_dl_set_call(libusb_exit);
247
+ libusb_dl_set_call(libusb_free_config_descriptor);
248
+ libusb_dl_set_call(libusb_free_device_list);
249
+ libusb_dl_set_call(libusb_get_config_descriptor);
250
+ libusb_dl_set_call(libusb_get_device_address);
251
+ libusb_dl_set_call(libusb_get_device_descriptor);
252
+ libusb_dl_set_call(libusb_get_device_list);
253
+ libusb_dl_set_call(libusb_get_string_descriptor_ascii);
254
+ libusb_dl_set_call(libusb_init);
255
+ libusb_dl_set_call(libusb_interrupt_transfer);
256
+ libusb_dl_set_call(libusb_kernel_driver_active);
257
+ libusb_dl_set_call(libusb_ref_device);
258
+ libusb_dl_set_call(libusb_release_interface);
259
+ libusb_dl_set_call(libusb_reset_device);
260
+ libusb_dl_set_call(libusb_set_configuration);
261
+ libusb_dl_set_call(libusb_set_debug);
262
+ libusb_dl_set_call(libusb_set_interface_alt_setting);
263
+ libusb_dl_set_call(libusb_unref_device);
264
+ return;
265
+failure:
266
+#ifdef HAVE_GNU_ERRNO_H
267
+ fprintf(stderr, "%s: error while loading " LIBUSB_1_0_SONAME " from libusb-0.1.so.4: %s\n",
268
+ program_invocation_name, dlerror());
269
+#else
270
+ fprintf(stderr, "libusb-compat: error while loading " LIBUSB_1_0_SONAME " from libusb-0.1.so.4: %s\n",
271
+ dlerror());
272
+#endif
273
+ exit(127);
274
+};
275
+
276
+static inline void libusb_dl_exit(void) {
277
+ dlclose(libusb_dl_handle);
278
+};
279
diff --git a/m4/au_check_lib_soname.m4 b/m4/au_check_lib_soname.m4
280
new file mode 100644
281
index 0000000..d7e8774
282
--- /dev/null
283
+++ b/m4/au_check_lib_soname.m4
284
285
+m4_pattern_allow([^AU_])
286
+
287
+# AU_CHECK_LIB_SONAME(VARIABLE, LIBRARY, FUNCTION,
288
+# [ACTION-IF-FOUND], [ACTION-IF-FOUND-BUT-NO-SONAME],
289
+# [ACTION-IF-NOT-FOUND],
290
+# [OTHER-LIBRARIES])
291
+#------------------------------------------------------------------------
292
+# This is similar to AC_CHECK_LIB, but also sets LIB${VARIABLE}_SONAME
293
+# If SONAME is not found and ACTION-IF-FOUND-BUT-NO-SONAME is called,
294
+# it still does things which does AC_CHECK_LIB for ACTION-IF-FOUND.
295
+AC_DEFUN([AU_CHECK_LIB_SONAME], [
296
+ AC_REQUIRE([LT_INIT])
297
+ AS_VAR_PUSHDEF([ac_Lib_SONAME], [au_cv_lib_soname_$1])
298
+ AC_ARG_VAR([$1][_SONAME], [SONAME of lib$2, overriding ldd check])
299
+ AC_CHECK_LIB($2,$3,[
300
+ AC_PATH_PROG([PATH_LDD], [ldd])
301
+ AC_CACHE_CHECK([for SONAME of lib$2], [ac_Lib_SONAME],[
302
+ AS_IF([test x"$[$1][_SONAME]" = x""], [
303
+ AS_IF([test x"$PATH_LDD" != x""], [
304
+ AS_VAR_SET([ac_Lib_SONAME], ["unknown"])
305
+ AU_CHECK_LIB_SONAME_LIBS="$LIBS"
306
+ LIBS="$LIBS $7 -l$2"
307
+ shrext_regexp=`echo "$shrext_cmds" | sed 's/\./\\\\./'`
308
+ AC_TRY_LINK([
309
+void libusb_close(void *);
310
+], [
311
+libusb_close((void*)0);
312
+],
313
+ [AS_VAR_SET([ac_Lib_SONAME], [`ldd conftest$ac_exeext | grep 'lib[$2]'$shrext_regexp | sed 's/^@<:@ \t@:>@*lib[$2]'$shrext_regexp'/lib[$2]'$shrext_regexp'/;s/@<:@ \t@:>@.*$//'`])])
314
+ LIBS="$AU_CHECK_LIB_SONAME_LIBS"
315
+ AS_IF([test x"$ac_Lib_SONAME" = x ],
316
+ [AS_VAR_SET([ac_Lib_SONAME], [unknown])])
317
+ AS_IF([test x"$ac_Lib_SONAME" != x"unknown" ], [
318
+ AS_VAR_SET([$1][_SONAME], ["$ac_Lib_SONAME"])
319
+ $4], [
320
+ $5])], [
321
+ AS_VAR_SET([ac_Lib_SONAME], [unknown])
322
+ $5])], [
323
+ AS_VAR_SET([ac_Lib_SONAME], ["$[$1][_SONAME]"])
324
+ $4])])],
325
+ [$6], [$7])
326
+ AS_VAR_POPDEF([ac_Lib_SONAME])
327
+])
328
diff --git a/m4/au_have_gnu_errno.m4 b/m4/au_have_gnu_errno.m4
329
new file mode 100644
330
index 0000000..c06cbf1
331
--- /dev/null
332
+++ b/m4/au_have_gnu_errno.m4
333
334
+m4_pattern_allow([^AU_])
335
+
336
+# AU_HAVE_GNU_ERRNO_H
337
+#--------------------
338
+# Check for GNU extensions of errno.h.
339
+AC_DEFUN([AU_HAVE_GNU_ERRNO_H], [
340
+ AC_CACHE_CHECK([for GNU extensions of errno.h], [ac_cv_have_gnu_errno_h],[
341
+ AC_TRY_COMPILE([
342
+#define _GNU_SOURCE
343
+#include <errno.h>
344
+ ], [char *testvar = program_invocation_name;],
345
+ [ac_cv_have_gnu_errno_h=yes], [ac_cv_have_gnu_errno_h=no])])
346
+ AS_IF([test x"$ac_cv_have_gnu_errno_h" = x"yes"], [
347
+ AC_DEFINE([HAVE_GNU_ERRNO_H], [1], [Define to 1 if you have the <errno.h> header file with GNU extensions.])
348
+ AC_DEFINE([_GNU_SOURCE], [], [Force _GNU_SOURCE from AC_HAVE[]_GNU_ERRNO_H.])
349
+ ])
350
+])
351
--
352
2.4.5
353
354