Commit a83b6b8a authored by Vincent Palatin's avatar Vincent Palatin Committed by Commit Bot

usb: uses lifeline file descriptors for webusb.

PermissionBroker is now able to re-attach properly kernel device drivers
to USB device interfaces on detecting the closure of a lifeline pipe from
Chrome.
Uses the new function for devices opened by webusb/chrome.usb.

Bug: 1090596
Change-Id: Iebeae21890869cbff565a6ac76f48a7daac04ee1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2475794
Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: default avatarFergus Dall <sidereal@google.com>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarNicholas Verne <nverne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#819292}
parent 7760e8f7
...@@ -34,6 +34,7 @@ UsbDeviceHandleAndroid::UsbDeviceHandleAndroid( ...@@ -34,6 +34,7 @@ UsbDeviceHandleAndroid::UsbDeviceHandleAndroid(
const base::android::JavaRef<jobject>& wrapper) const base::android::JavaRef<jobject>& wrapper)
: UsbDeviceHandleUsbfs(device, : UsbDeviceHandleUsbfs(device,
std::move(fd), std::move(fd),
base::ScopedFD(),
UsbService::CreateBlockingTaskRunner()), UsbService::CreateBlockingTaskRunner()),
j_object_(wrapper) {} j_object_(wrapper) {}
......
...@@ -141,6 +141,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper { ...@@ -141,6 +141,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper {
public: public:
BlockingTaskRunnerHelper( BlockingTaskRunnerHelper(
base::ScopedFD fd, base::ScopedFD fd,
base::ScopedFD lifeline_fd,
scoped_refptr<UsbDeviceHandleUsbfs> device_handle, scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
scoped_refptr<base::SequencedTaskRunner> task_runner); scoped_refptr<base::SequencedTaskRunner> task_runner);
~BlockingTaskRunnerHelper(); ~BlockingTaskRunnerHelper();
...@@ -162,6 +163,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper { ...@@ -162,6 +163,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper {
void OnFileCanWriteWithoutBlocking(); void OnFileCanWriteWithoutBlocking();
base::ScopedFD fd_; base::ScopedFD fd_;
base::ScopedFD lifeline_fd_;
scoped_refptr<UsbDeviceHandleUsbfs> device_handle_; scoped_refptr<UsbDeviceHandleUsbfs> device_handle_;
scoped_refptr<base::SequencedTaskRunner> task_runner_; scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_;
...@@ -208,9 +210,11 @@ struct UsbDeviceHandleUsbfs::Transfer final { ...@@ -208,9 +210,11 @@ struct UsbDeviceHandleUsbfs::Transfer final {
UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::BlockingTaskRunnerHelper( UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::BlockingTaskRunnerHelper(
base::ScopedFD fd, base::ScopedFD fd,
base::ScopedFD lifeline_fd,
scoped_refptr<UsbDeviceHandleUsbfs> device_handle, scoped_refptr<UsbDeviceHandleUsbfs> device_handle,
scoped_refptr<base::SequencedTaskRunner> task_runner) scoped_refptr<base::SequencedTaskRunner> task_runner)
: fd_(std::move(fd)), : fd_(std::move(fd)),
lifeline_fd_(std::move(lifeline_fd)),
device_handle_(std::move(device_handle)), device_handle_(std::move(device_handle)),
task_runner_(std::move(task_runner)) {} task_runner_(std::move(task_runner)) {}
...@@ -432,6 +436,7 @@ void UsbDeviceHandleUsbfs::Transfer::RunIsochronousCallback( ...@@ -432,6 +436,7 @@ void UsbDeviceHandleUsbfs::Transfer::RunIsochronousCallback(
UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs(
scoped_refptr<UsbDevice> device, scoped_refptr<UsbDevice> device,
base::ScopedFD fd, base::ScopedFD fd,
base::ScopedFD lifeline_fd,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
: device_(device), : device_(device),
fd_(fd.get()), fd_(fd.get()),
...@@ -441,8 +446,8 @@ UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs( ...@@ -441,8 +446,8 @@ UsbDeviceHandleUsbfs::UsbDeviceHandleUsbfs(
DCHECK(fd.is_valid()); DCHECK(fd.is_valid());
DCHECK(blocking_task_runner_); DCHECK(blocking_task_runner_);
helper_.reset( helper_ = std::make_unique<BlockingTaskRunnerHelper>(
new BlockingTaskRunnerHelper(std::move(fd), this, task_runner_)); std::move(fd), std::move(lifeline_fd), this, task_runner_);
blocking_task_runner_->PostTask( blocking_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::Start, FROM_HERE, base::BindOnce(&BlockingTaskRunnerHelper::Start,
base::Unretained(helper_.get()))); base::Unretained(helper_.get())));
...@@ -472,6 +477,9 @@ void UsbDeviceHandleUsbfs::Close() { ...@@ -472,6 +477,9 @@ void UsbDeviceHandleUsbfs::Close() {
// The device is no longer attached so we don't have any endpoints either. // The device is no longer attached so we don't have any endpoints either.
endpoints_.clear(); endpoints_.clear();
// The destruction of the |helper_| below will close the lifeline pipe if it
// exists and re-attach kernel driver.
// Releases |helper_|. // Releases |helper_|.
blocking_task_runner_->PostTask( blocking_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&UsbDeviceHandleUsbfs::CloseBlocking, this)); FROM_HERE, base::BindOnce(&UsbDeviceHandleUsbfs::CloseBlocking, this));
......
...@@ -33,6 +33,7 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle { ...@@ -33,6 +33,7 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle {
UsbDeviceHandleUsbfs( UsbDeviceHandleUsbfs(
scoped_refptr<UsbDevice> device, scoped_refptr<UsbDevice> device,
base::ScopedFD fd, base::ScopedFD fd,
base::ScopedFD lifeline_fd,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
// UsbDeviceHandle implementation. // UsbDeviceHandle implementation.
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/files/file_util.h"
#include "base/location.h" #include "base/location.h"
#include "base/posix/eintr_wrapper.h" #include "base/posix/eintr_wrapper.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
...@@ -23,6 +24,10 @@ ...@@ -23,6 +24,10 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "chromeos/dbus/permission_broker/permission_broker_client.h" #include "chromeos/dbus/permission_broker/permission_broker_client.h"
namespace {
constexpr uint32_t kAllInterfacesMask = ~0U;
} // namespace
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
namespace device { namespace device {
...@@ -48,11 +53,20 @@ void UsbDeviceLinux::Open(OpenCallback callback) { ...@@ -48,11 +53,20 @@ void UsbDeviceLinux::Open(OpenCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
// create the pipe used as a lifetime to re-attach the original kernel driver
// to the USB device in permission_broker.
base::ScopedFD read_end, write_end;
if (!base::CreatePipe(&read_end, &write_end, /*non_blocking*/ true)) {
LOG(ERROR) << "Couldn't create pipe for USB device " << device_path_;
std::move(callback).Run(nullptr);
return;
}
auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
chromeos::PermissionBrokerClient::Get()->OpenPath( chromeos::PermissionBrokerClient::Get()->ClaimDevicePath(
device_path_, device_path_, kAllInterfacesMask, read_end.get(),
base::BindOnce(&UsbDeviceLinux::OnOpenRequestComplete, this, base::BindOnce(&UsbDeviceLinux::OnOpenRequestComplete, this,
copyable_callback), copyable_callback, std::move(write_end)),
base::BindOnce(&UsbDeviceLinux::OnOpenRequestError, this, base::BindOnce(&UsbDeviceLinux::OnOpenRequestError, this,
copyable_callback)); copyable_callback));
#else #else
...@@ -69,13 +83,14 @@ void UsbDeviceLinux::Open(OpenCallback callback) { ...@@ -69,13 +83,14 @@ void UsbDeviceLinux::Open(OpenCallback callback) {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
void UsbDeviceLinux::OnOpenRequestComplete(OpenCallback callback, void UsbDeviceLinux::OnOpenRequestComplete(OpenCallback callback,
base::ScopedFD lifeline_fd,
base::ScopedFD fd) { base::ScopedFD fd) {
if (!fd.is_valid()) { if (!fd.is_valid()) {
USB_LOG(EVENT) << "Did not get valid device handle from permission broker."; USB_LOG(EVENT) << "Did not get valid device handle from permission broker.";
std::move(callback).Run(nullptr); std::move(callback).Run(nullptr);
return; return;
} }
Opened(std::move(fd), std::move(callback), Opened(std::move(fd), std::move(lifeline_fd), std::move(callback),
UsbService::CreateBlockingTaskRunner()); UsbService::CreateBlockingTaskRunner());
} }
...@@ -97,7 +112,8 @@ void UsbDeviceLinux::OpenOnBlockingThread( ...@@ -97,7 +112,8 @@ void UsbDeviceLinux::OpenOnBlockingThread(
if (fd.is_valid()) { if (fd.is_valid()) {
task_runner->PostTask( task_runner->PostTask(
FROM_HERE, base::BindOnce(&UsbDeviceLinux::Opened, this, std::move(fd), FROM_HERE, base::BindOnce(&UsbDeviceLinux::Opened, this, std::move(fd),
std::move(callback), blocking_task_runner)); base::ScopedFD(), std::move(callback),
blocking_task_runner));
} else { } else {
USB_PLOG(EVENT) << "Failed to open " << device_path_; USB_PLOG(EVENT) << "Failed to open " << device_path_;
task_runner->PostTask(FROM_HERE, task_runner->PostTask(FROM_HERE,
...@@ -109,11 +125,12 @@ void UsbDeviceLinux::OpenOnBlockingThread( ...@@ -109,11 +125,12 @@ void UsbDeviceLinux::OpenOnBlockingThread(
void UsbDeviceLinux::Opened( void UsbDeviceLinux::Opened(
base::ScopedFD fd, base::ScopedFD fd,
base::ScopedFD lifeline_fd,
OpenCallback callback, OpenCallback callback,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) { scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<UsbDeviceHandle> device_handle = scoped_refptr<UsbDeviceHandle> device_handle = new UsbDeviceHandleUsbfs(
new UsbDeviceHandleUsbfs(this, std::move(fd), blocking_task_runner); this, std::move(fd), std::move(lifeline_fd), blocking_task_runner);
handles().push_back(device_handle.get()); handles().push_back(device_handle.get());
std::move(callback).Run(device_handle); std::move(callback).Run(device_handle);
} }
......
...@@ -52,7 +52,9 @@ class UsbDeviceLinux : public UsbDevice { ...@@ -52,7 +52,9 @@ class UsbDeviceLinux : public UsbDevice {
private: private:
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
void OnOpenRequestComplete(OpenCallback callback, base::ScopedFD fd); void OnOpenRequestComplete(OpenCallback callback,
base::ScopedFD fd,
base::ScopedFD lifeline_fd);
void OnOpenRequestError(OpenCallback callback, void OnOpenRequestError(OpenCallback callback,
const std::string& error_name, const std::string& error_name,
const std::string& error_message); const std::string& error_message);
...@@ -63,6 +65,7 @@ class UsbDeviceLinux : public UsbDevice { ...@@ -63,6 +65,7 @@ class UsbDeviceLinux : public UsbDevice {
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
void Opened(base::ScopedFD fd, void Opened(base::ScopedFD fd,
base::ScopedFD lifeline_fd,
OpenCallback callback, OpenCallback callback,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment