enable udev support;

if libudev-openbsd is installed, chromium will use its monitoring capabilities
so that e.g. fido(4) keys can be plugged in anytime during an authentication
process instead of enumerating devices once on startup
This commit is contained in:
robert 2022-11-08 19:29:19 +00:00
parent 34b2ae4830
commit dfd6be8623
10 changed files with 199 additions and 127 deletions

View File

@ -9,7 +9,7 @@ COMMENT= Chromium browser
V= 107.0.5304.87
DISTNAME= chromium-${V}
REVISION= 1
REVISION= 2
DISTFILES+= ${CHROMIUM_DISTFILES} \
${PROFILE_DISTFILES}:0 \
@ -165,7 +165,7 @@ GN_ARGS= enable_nacl=false \
extra_cppflags=\"-idirafter ${LOCALBASE}/include -idirafter ${X11BASE}/include\" \
fatal_linker_warnings=false \
use_custom_libcxx=false \
use_udev=false
use_udev=true
# notyet
GN_ARGS+= use_vaapi=false

View File

@ -1,6 +1,15 @@
Index: components/storage_monitor/BUILD.gn
--- components/storage_monitor/BUILD.gn.orig
+++ components/storage_monitor/BUILD.gn
@@ -71,7 +71,7 @@ static_library("storage_monitor") {
deps += [ "//services/device/public/mojom" ]
}
} else if (is_linux || is_chromeos_lacros) {
- if (use_udev) {
+ if (use_udev && !is_bsd) {
sources += [
"mtab_watcher_linux.cc",
"mtab_watcher_linux.h",
@@ -175,7 +175,7 @@ source_set("unit_tests") {
"storage_monitor_chromeos_unittest.cc",
]

View File

@ -0,0 +1,12 @@
Index: device/gamepad/BUILD.gn
--- device/gamepad/BUILD.gn.orig
+++ device/gamepad/BUILD.gn
@@ -98,7 +98,7 @@ component("gamepad") {
"hid_writer_linux.cc",
"hid_writer_linux.h",
]
- if (use_udev) {
+ if (use_udev && !is_bsd) {
sources += [
"gamepad_device_linux.cc",
"gamepad_device_linux.h",

View File

@ -0,0 +1,12 @@
Index: services/device/BUILD.gn
--- services/device/BUILD.gn.orig
+++ services/device/BUILD.gn
@@ -16,7 +16,7 @@ if (is_android) {
}
is_serial_enabled_platform =
- is_win || ((is_linux || is_chromeos) && use_udev) || is_mac
+ is_win || ((!is_bsd && is_linux || is_chromeos) && use_udev) || is_mac
source_set("lib") {
# This should be visible only to embedders of the Device Service, and the

View File

@ -1,10 +1,11 @@
Index: services/device/hid/BUILD.gn
--- services/device/hid/BUILD.gn.orig
+++ services/device/hid/BUILD.gn
@@ -35,6 +35,25 @@ source_set("hid") {
@@ -35,7 +35,26 @@ source_set("hid") {
"//services/device/public/mojom",
]
- if ((is_linux || is_chromeos) && use_udev) {
+ if (is_openbsd) {
+ sources += [
+ "hid_connection_fido.cc",
@ -24,6 +25,7 @@ Index: services/device/hid/BUILD.gn
+ ]
+ }
+
if ((is_linux || is_chromeos) && use_udev) {
+ if ((is_linux || is_chromeos) && !is_bsd && use_udev) {
sources += [
"hid_connection_linux.cc",
"hid_connection_linux.h",

View File

@ -1,7 +1,7 @@
Index: services/device/hid/hid_service_fido.cc
--- services/device/hid/hid_service_fido.cc.orig
+++ services/device/hid/hid_service_fido.cc
@@ -0,0 +1,392 @@
@@ -0,0 +1,399 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
@ -12,6 +12,7 @@ Index: services/device/hid/hid_service_fido.cc
+#include <poll.h>
+#include <stdint.h>
+
+#include <dlfcn.h>
+#include <fido.h>
+
+#include <limits>
@ -37,15 +38,10 @@ Index: services/device/hid/hid_service_fido.cc
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+#include "components/device_event_log/device_event_log.h"
+#include "device/udev_linux/scoped_udev.h"
+#include "device/udev_linux/udev_watcher.h"
+#include "services/device/hid/hid_connection_fido.h"
+
+// TODO(huangs): Enable for IS_CHROMEOS_LACROS. This will simplify crosapi so
+// that it won't need to pass HidManager around (crbug.com/1109621).
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "base/system/sys_info.h"
+#include "chromeos/dbus/permission_broker/permission_broker_client.h" // nogncheck
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
+namespace device {
+
+namespace {
@ -148,7 +144,7 @@ Index: services/device/hid/hid_service_fido.cc
+ base::ScopedFD fd;
+};
+
+class HidServiceFido::BlockingTaskRunnerHelper {
+class HidServiceFido::BlockingTaskRunnerHelper : public UdevWatcher::Observer {
+ public:
+ BlockingTaskRunnerHelper(base::WeakPtr<HidServiceFido> service)
+ : service_(std::move(service)),
@ -159,59 +155,22 @@ Index: services/device/hid/hid_service_fido.cc
+ BlockingTaskRunnerHelper(const BlockingTaskRunnerHelper&) = delete;
+ BlockingTaskRunnerHelper& operator=(const BlockingTaskRunnerHelper&) = delete;
+
+ ~BlockingTaskRunnerHelper() = default;
+ ~BlockingTaskRunnerHelper() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ }
+
+ void Start() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ fido_dev_info_t *devlist = NULL;
+ fido_dev_t *dev = NULL;
+ size_t devlist_len = 0, i;
+ const char *path;
+ int r;
+ const int MAX_FIDO_DEVICES = 256;
+
+ if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
+ HID_LOG(ERROR) << "fido_dev_info_new failed";
+ goto out;
+ void *library = dlopen("libudev.so", RTLD_NOW | RTLD_LOCAL);
+ if (library) {
+ dlclose(library);
+ watcher_ = UdevWatcher::StartWatching(this);
+ watcher_->EnumerateExistingDevices();
+ } else {
+ HID_LOG(ERROR) << "No udev available, failling back to single enumeration";
+ WalkFidoDevices(nullptr);
+ }
+ if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES, &devlist_len)) !=
+ FIDO_OK) {
+ HID_LOG(ERROR) << "fido_dev_info_manifest: " << fido_strerr(r);
+ goto out;
+ }
+
+ HID_LOG(EVENT) << "fido_dev_info_manifest found " << devlist_len
+ << " device(s)";
+
+ for (i = 0; i < devlist_len; i++) {
+ const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
+ if (di == NULL) {
+ HID_LOG(ERROR) << "fido_dev_info_ptr " << i << " failed";
+ continue;
+ }
+ if ((path = fido_dev_info_path(di)) == NULL) {
+ HID_LOG(ERROR) << "fido_dev_info_path " << i << " failed";
+ continue;
+ }
+ HID_LOG(EVENT) << "trying device " << i << ": " << path;
+ if ((dev = fido_dev_new()) == NULL) {
+ HID_LOG(ERROR) << "fido_dev_new failed";
+ continue;
+ }
+ if ((r = fido_dev_open(dev, path)) != FIDO_OK) {
+ HID_LOG(ERROR) << "fido_dev_open failed " << path;
+ fido_dev_free(&dev);
+ continue;
+ }
+ OnDeviceAdded(di);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ }
+
+ out:
+ if (devlist != NULL)
+ fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
+
+ task_runner_->PostTask(
+ FROM_HERE,
@ -219,37 +178,122 @@ Index: services/device/hid/hid_service_fido.cc
+ }
+
+ private:
+ void OnDeviceAdded(const fido_dev_info_t *di) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ base::ScopedBlockingCall scoped_blocking_call(
+ FROM_HERE, base::BlockingType::MAY_BLOCK);
+ void WalkFidoDevices(const char *name) {
+ fido_dev_info_t *devlist = NULL;
+ fido_dev_t *dev = NULL;
+ size_t devlist_len = 0, i;
+ const char *path;
+ int r;
+ const int MAX_FIDO_DEVICES = 256;
+
+ if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
+ HID_LOG(ERROR) << "fido_dev_info_new failed";
+ goto out;
+ }
+ if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES, &devlist_len)) !=
+ FIDO_OK) {
+ HID_LOG(ERROR) << "fido_dev_info_manifest: " << fido_strerr(r);
+ goto out;
+ }
+
+ HID_LOG(EVENT) << "fido_dev_info_manifest found " << devlist_len
+ << " device(s)";
+
+ for (i = 0; i < devlist_len; i++) {
+ const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
+
+ if (di == NULL) {
+ HID_LOG(ERROR) << "fido_dev_info_ptr " << i << " failed";
+ continue;
+ }
+
+ if ((path = fido_dev_info_path(di)) == NULL) {
+ HID_LOG(ERROR) << "fido_dev_info_path " << i << " failed";
+ continue;
+ }
+
+ if (name != nullptr && !strcmp(path, name)) {
+ HID_LOG(EVENT) << "hotplug device " << i << ": " << path;
+ OnFidoDeviceAdded(di);
+ break;
+ }
+
+ HID_LOG(EVENT) << "trying device " << i << ": " << path;
+ if ((dev = fido_dev_new()) == NULL) {
+ HID_LOG(ERROR) << "fido_dev_new failed";
+ continue;
+ }
+
+ if ((r = fido_dev_open(dev, path)) != FIDO_OK) {
+ HID_LOG(ERROR) << "fido_dev_open failed " << path;
+ fido_dev_free(&dev);
+ continue;
+ }
+
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+
+ OnFidoDeviceAdded(di);
+ }
+ out:
+ if (devlist != NULL)
+ fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
+ }
+
+ void OnFidoDeviceAdded(const fido_dev_info_t *di) {
+ auto null_as_empty = [](const char *r) -> std::string {
+ return (r != nullptr) ? r : "";
+ };
+ std::string device_node(null_as_empty(fido_dev_info_path(di)));
+ std::vector<uint8_t> report_descriptor(
+ kU2fReportDesc, kU2fReportDesc + sizeof(kU2fReportDesc));
+ scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfo(
+ device_node, /*physical_device_id=*/"", fido_dev_info_vendor(di),
+
+ auto device_info = base::MakeRefCounted<HidDeviceInfo>(
+ device_node, /*physical_device_id*/"", fido_dev_info_vendor(di),
+ fido_dev_info_product(di), null_as_empty(fido_dev_info_product_string(di)),
+ null_as_empty(fido_dev_info_manufacturer_string(di)),
+ device::mojom::HidBusType::kHIDBusTypeUSB, report_descriptor,
+ device_node));
+
+ task_runner_->PostTask(FROM_HERE, base::BindOnce(&HidServiceFido::AddDevice,
+ service_, device_info));
+ device::mojom::HidBusType::kHIDBusTypeUSB, report_descriptor,
+ device_node);
+
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&HidServiceFido::AddDevice, service_, device_info));
+ }
+
+ void OnDeviceRemoved(std::string device_node) {
+ // UdevWatcher::Observer
+ void OnDeviceAdded(ScopedUdevDevicePtr device) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ base::ScopedBlockingCall scoped_blocking_call(
+ FROM_HERE, base::BlockingType::MAY_BLOCK);
+ task_runner_->PostTask(FROM_HERE, base::BindOnce(&HidServiceFido::RemoveDevice,
+ service_, device_node));
+
+ const char* subsystem = udev_device_get_subsystem(device.get());
+ if (!subsystem || strcmp(subsystem, "fido") != 0)
+ return;
+
+ const char* device_path = udev_device_get_syspath(device.get());
+ if (!device_path)
+ return;
+
+ WalkFidoDevices(device_path);
+ }
+
+ void OnDeviceRemoved(ScopedUdevDevicePtr device) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ base::ScopedBlockingCall scoped_blocking_call(
+ FROM_HERE, base::BlockingType::MAY_BLOCK);
+
+ const char* device_path = udev_device_get_syspath(device.get());
+ if (device_path) {
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&HidServiceFido::RemoveDevice, service_,
+ std::string(device_path)));
+ }
+ }
+
+ void OnDeviceChanged(ScopedUdevDevicePtr) override {}
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ std::unique_ptr<UdevWatcher> watcher_;
+
+ // This weak pointer is only valid when checked on this task runner.
+ base::WeakPtr<HidServiceFido> service_;
@ -288,19 +332,6 @@ Index: services/device/hid/hid_service_fido.cc
+ }
+ scoped_refptr<HidDeviceInfo> device_info = map_entry->second;
+
+// TODO(huangs): Enable for IS_CHROMEOS_LACROS for crbug.com/1223456.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ auto split_callback = base::SplitOnceCallback(std::move(callback));
+ chromeos::PermissionBrokerClient::Get()->OpenPath(
+ device_info->device_node(),
+ base::BindOnce(&HidServiceFido::OnPathOpenComplete,
+ std::make_unique<ConnectParams>(
+ device_info, allow_protected_reports,
+ allow_fido_reports, std::move(split_callback.first))),
+ base::BindOnce(&HidServiceFido::OnPathOpenError,
+ device_info->device_node(),
+ std::move(split_callback.second)));
+#else
+ auto params =
+ std::make_unique<ConnectParams>(device_info, allow_protected_reports,
+ allow_fido_reports, std::move(callback));
@ -309,30 +340,8 @@ Index: services/device/hid/hid_service_fido.cc
+ blocking_task_runner->PostTask(
+ FROM_HERE, base::BindOnce(&HidServiceFido::OpenOnBlockingThread,
+ std::move(params)));
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+}
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+
+// static
+void HidServiceFido::OnPathOpenComplete(std::unique_ptr<ConnectParams> params,
+ base::ScopedFD fd) {
+ params->fd = std::move(fd);
+ FinishOpen(std::move(params));
+}
+
+// static
+void HidServiceFido::OnPathOpenError(const std::string& device_path,
+ ConnectCallback callback,
+ const std::string& error_name,
+ const std::string& error_message) {
+ HID_LOG(EVENT) << "Permission broker failed to open '" << device_path
+ << "': " << error_name << ": " << error_message;
+ std::move(callback).Run(nullptr);
+}
+
+#else
+
+// static
+void HidServiceFido::OpenOnBlockingThread(
+ std::unique_ptr<ConnectParams> params) {
@ -374,8 +383,6 @@ Index: services/device/hid/hid_service_fido.cc
+ std::move(params)));
+}
+
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
+// static
+void HidServiceFido::FinishOpen(std::unique_ptr<ConnectParams> params) {
+ DCHECK(params->fd.is_valid());

View File

@ -0,0 +1,12 @@
Index: services/device/public/mojom/BUILD.gn
--- services/device/public/mojom/BUILD.gn.orig
+++ services/device/public/mojom/BUILD.gn
@@ -91,7 +91,7 @@ mojom("device_service") {
disable_variants = true
enabled_features = []
- if ((is_linux || is_chromeos) && use_udev) {
+ if ((is_linux || is_chromeos) && !is_bsd && use_udev) {
enabled_features += [ "enable_input_device_manager" ]
}

View File

@ -1,17 +1,12 @@
Index: services/device/serial/BUILD.gn
--- services/device/serial/BUILD.gn.orig
+++ services/device/serial/BUILD.gn
@@ -83,6 +83,13 @@ if (is_win || ((is_linux || is_chromeos) && use_udev)
]
}
@@ -5,7 +5,7 @@
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/features.gni")
+ if (is_bsd) {
+ sources -= [
+ "serial_device_enumerator_linux.cc",
+ "serial_device_enumerator_linux.h"
+ ]
+ }
+
if (use_udev) {
deps += [ "//device/udev_linux" ]
}
-if (is_win || ((is_linux || is_chromeos) && use_udev) || is_mac) {
+if (is_win || ((!is_bsd && is_linux || is_chromeos) && use_udev) || is_mac) {
config("platform_support") {
visibility = [ ":serial" ]
if (is_win) {

View File

@ -1,7 +1,15 @@
Index: services/device/usb/usb_service.cc
--- services/device/usb/usb_service.cc.orig
+++ services/device/usb/usb_service.cc
@@ -29,6 +29,10 @@
@@ -22,13 +22,17 @@
#if BUILDFLAG(IS_ANDROID)
#include "services/device/usb/usb_service_android.h"
-#elif defined(USE_UDEV)
+#elif defined(USE_UDEV) && !BUILDFLAG(IS_BSD)
#include "services/device/usb/usb_service_linux.h"
#elif BUILDFLAG(IS_MAC)
#include "services/device/usb/usb_service_impl.h"
#include "services/device/usb/usb_service_mac.h"
#elif BUILDFLAG(IS_WIN)
#include "services/device/usb/usb_service_win.h"
@ -12,6 +20,15 @@ Index: services/device/usb/usb_service.cc
#endif
namespace device {
@@ -51,7 +55,7 @@ constexpr base::TaskTraits UsbService::kBlockingTaskTr
std::unique_ptr<UsbService> UsbService::Create() {
#if BUILDFLAG(IS_ANDROID)
return base::WrapUnique(new UsbServiceAndroid());
-#elif defined(USE_UDEV)
+#elif defined(USE_UDEV) && !BUILDFLAG(IS_BSD)
return base::WrapUnique(new UsbServiceLinux());
#elif BUILDFLAG(IS_WIN)
return base::WrapUnique(new UsbServiceWin());
@@ -60,6 +64,8 @@ std::unique_ptr<UsbService> UsbService::Create() {
return base::WrapUnique(new UsbServiceMac());
else

View File

@ -19,7 +19,7 @@ Index: third_party/libusb/BUILD.gn
sources += [
"src/libusb/os/linux_usbfs.c",
"src/libusb/os/linux_usbfs.h",
@@ -127,6 +127,16 @@ static_library("libusb") {
@@ -127,11 +127,21 @@ static_library("libusb") {
]
}
@ -36,6 +36,12 @@ Index: third_party/libusb/BUILD.gn
if (is_chromeos_ash) {
defines += [ "USBI_TIMERFD_AVAILABLE" ]
}
- if (use_udev) {
+ if (use_udev && !is_bsd) {
sources += [ "src/libusb/os/linux_udev.cc" ]
defines += [
"HAVE_LIBUDEV=1",
@@ -140,7 +150,7 @@ static_library("libusb") {
deps += [ "//build/linux/libudev" ]
}