From 8633dfb3c90dd00abd97ddfe6653d56d94ad997e Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Mon, 29 Jun 2015 12:31:05 +0200 Subject: [PATCH] Allow to obtain fd from USB Security Daemon Tizen don't allow applications to directly open device nodes for communication with USB devices. We have our own daemon (USD - USB Security Daemon) which holds the policy of accessing USB devices. Each app which would like to communicate with device has to ask USD to open suitable file and pass fds to app. This patch updates libusb and first tries to open device node directly and only if it fails asks USD to open fds. This allows to not influence existing libusb users which has root rights and check USD permissions only for external applications. Change-Id: I9dcac37ccc8ae86cef4d22965744781307940e61 Signed-off-by: Krzysztof Opasiak [Rebase patch onto new library version] Signed-off-by: Krzysztof Opasiak --- configure.ac | 11 ++++++ libusb/Makefile.am | 7 ++++ libusb/os/linux_usbfs.c | 101 ++++++++++++++++++++++++++++++++++++++++++------ packaging/libusb.spec | 6 ++- 4 files changed, 112 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index c00af33..7eb4628 100644 --- a/configure.ac +++ b/configure.ac @@ -107,6 +107,16 @@ case $backend in linux) AC_DEFINE(OS_LINUX, 1, [Linux backend]) AC_SUBST(OS_LINUX) + AC_ARG_ENABLE([usd], + [AC_HELP_STRING([--enable-usd], [Use USB security daemon to obtain dev node fds [default=no]])], + [], [enable_usd="no"]) + if test "x$enable_usd" = "xyes"; then + PKG_CHECK_MODULES([USD], [capi-system-usbhost-usd]) + AC_DEFINE(USE_USD, 1, [Use USB security daemon to obtain dev node fds]) + fi + + AC_SUBST(USE_USD) + AC_SEARCH_LIBS(clock_gettime, rt, [], [], -pthread) AC_ARG_ENABLE([udev], [AC_HELP_STRING([--enable-udev], [use udev for device enumeration and hotplug support (recommended) [default=yes]])], @@ -213,6 +223,7 @@ AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix) AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes") AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes) AM_CONDITIONAL(USE_USBDK, test "x$enable_usbdk" = xyes) +AM_CONDITIONAL(USE_USD, test "x$enable_usd" = xyes) if test "$threads" = posix; then AC_DEFINE(THREADS_POSIX, 1, [Use POSIX Threads]) fi diff --git a/libusb/Makefile.am b/libusb/Makefile.am index b1b892d..2731986 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -102,3 +102,10 @@ libusb_1_0_la_SOURCES = libusbi.h libusb.h version.h version_nano.h \ hdrdir = $(includedir)/libusb-1.0 hdr_HEADERS = libusb.h + +if OS_LINUX +if USE_USD +libusb_1_0_la_CFLAGS += $(USD_CFLAGS) +libusb_1_0_la_LIBADD = $(USD_LIBS) +endif +endif \ No newline at end of file diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 9cbeb80..f6ee9a3 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -39,6 +39,11 @@ #include #include +/* Tizen specific */ +#ifdef USE_USD +#include +#endif + #include "libusbi.h" #include "linux_usbfs.h" @@ -180,12 +185,74 @@ struct linux_transfer_priv { int iso_packet_offset; }; +static int _direct_open_device(struct libusb_context *ctx, const char *path, + mode_t mode, int silent) +{ + int fd; + int delay = 10000; + + fd = open(path, mode); + if (fd != -1) + return fd; /* Success */ + + if (errno == ENOENT) { + if (!silent) + usbi_err(ctx, "File doesn't exist," + "wait %d ms and try again\n", delay/1000); + + /* Wait 10ms for USB device path creation.*/ + usleep(delay); + + fd = open(path, mode); + if (fd != -1) + return fd; /* Success */ + } + + return fd; +} + +#ifdef USE_USD +static int _ask_for_open(const char *path, mode_t mode, int silent) +{ + int ret; + int fd; + + ret = usd_open_usb_device(path, &fd); + if (ret != USD_API_SUCCESS) { + /* + * We have an error so let's set errno correctly + * just like open does + */ + switch (ret) { + case USD_API_ERROR_ACCESS_DENIED: + case USD_API_ERROR_SOCKET: + case USD_API_ERROR_AUTHENTICATION_FAILED: + errno = EACCES; + break; + + case USD_API_ERROR_INPUT_PARAM: + case USD_API_ERROR_FILE_NOT_EXIST: + errno = ENOENT; + break; + default: + errno = EINVAL; + break; + } + + ret = -1; + } else { + ret = fd; + } + + return ret; +} +#endif /* USE_USD */ + static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) { struct libusb_context *ctx = DEVICE_CTX(dev); char path[PATH_MAX]; int fd; - int delay = 10000; if (usbdev_names) snprintf(path, PATH_MAX, "%s/usbdev%d.%d", @@ -194,22 +261,34 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent) snprintf(path, PATH_MAX, "%s/%03d/%03d", usbfs_path, dev->bus_number, dev->device_address); - fd = open(path, mode); + fd = _direct_open_device(ctx, path, mode, silent); if (fd != -1) return fd; /* Success */ - if (errno == ENOENT) { - if (!silent) - usbi_err(ctx, "File doesn't exist, wait %d ms and try again", delay/1000); - - /* Wait 10ms for USB device path creation.*/ - nanosleep(&(struct timespec){delay / 1000000, (delay * 1000) % 1000000000UL}, NULL); +#ifdef USE_USD + /* + * If we are here, we were unable to go simple + * path and open the device directly. In Tizen + * we have USB security daemon (USD) which + * manages access rights to USB device nodes. + * Now let's ask him to open this device node + * for us. + */ - fd = open(path, mode); + /* + * USD is applicable only for RW access. + */ + if (mode & O_RDWR) { + if (!silent) + usbi_info(ctx, "No direct access to device node: %s. " + "Trying to use USD", path); + + fd = _ask_for_open(path, mode, silent); if (fd != -1) - return fd; /* Success */ + return fd; } - +#endif /* USE_USD */ + if (!silent) { usbi_err(ctx, "libusb couldn't open USB device %s: %s", path, strerror(errno)); diff --git a/packaging/libusb.spec b/packaging/libusb.spec index 66d064e..1d7a227 100644 --- a/packaging/libusb.spec +++ b/packaging/libusb.spec @@ -10,6 +10,7 @@ Source1: baselibs.conf Source1001: libusb.manifest BuildRequires: pkg-config BuildRequires: systemd-devel +BuildRequires: pkgconfig(capi-system-usbhost-usd) %description Libusb is a library that allows userspace access to USB devices. @@ -28,9 +29,10 @@ Libusb is a library that allows userspace access to USB devices. cp %{SOURCE1001} . %build -%configure\ +%reconfigure\ --with-pic\ - --disable-static + --disable-static\ + --enable-usd make %{?_smp_mflags} %install -- 2.7.4