summaryrefslogtreecommitdiffstats
path: root/device/hid/hid_service_linux.cc
diff options
context:
space:
mode:
authorreillyg <reillyg@chromium.org>2015-07-10 14:36:10 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-10 21:37:06 +0000
commite6aead1fa5623666c4e5cd78ce17e1935ee769b1 (patch)
tree3f5963630f62ab1136fb4a5dfb55e5a8fd695a40 /device/hid/hid_service_linux.cc
parent047ad603c025597829bb6e0482752ad95b2e431c (diff)
downloadchromium_src-e6aead1fa5623666c4e5cd78ce17e1935ee769b1.zip
chromium_src-e6aead1fa5623666c4e5cd78ce17e1935ee769b1.tar.gz
chromium_src-e6aead1fa5623666c4e5cd78ce17e1935ee769b1.tar.bz2
Use permission_broker's OpenPath method to open HID devices.
This new method allows Chrome to open device nodes without having to chmod them to a group of which Chrome is a member and allows the permission broker to set opens on the file descriptor before passing it to Chrome. This is a win for security and future extensibility. BUG=None Review URL: https://codereview.chromium.org/1233753002 Cr-Commit-Position: refs/heads/master@{#338367}
Diffstat (limited to 'device/hid/hid_service_linux.cc')
-rw-r--r--device/hid/hid_service_linux.cc91
1 files changed, 52 insertions, 39 deletions
diff --git a/device/hid/hid_service_linux.cc b/device/hid/hid_service_linux.cc
index 500f7b8..713b447 100644
--- a/device/hid/hid_service_linux.cc
+++ b/device/hid/hid_service_linux.cc
@@ -23,6 +23,7 @@
#include "device/hid/hid_connection_linux.h"
#include "device/hid/hid_device_info_linux.h"
#include "device/udev_linux/scoped_udev.h"
+#include "net/base/net_util.h"
#if defined(OS_CHROMEOS)
#include "base/sys_info.h"
@@ -227,25 +228,17 @@ void HidServiceLinux::Connect(const HidDeviceId& device_id,
device_info, callback, task_runner_, file_task_runner_));
#if defined(OS_CHROMEOS)
- if (base::SysInfo::IsRunningOnChromeOS()) {
- chromeos::PermissionBrokerClient* client =
- chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
- DCHECK(client) << "Could not get permission broker client.";
- if (client) {
- client->RequestPathAccess(
- device_info->device_node(), -1,
- base::Bind(&HidServiceLinux::OnRequestPathAccessComplete,
- base::Passed(&params)));
- } else {
- task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
- }
- return;
- }
+ chromeos::PermissionBrokerClient* client =
+ chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
+ DCHECK(client) << "Could not get permission broker client.";
+ client->OpenPath(
+ device_info->device_node(),
+ base::Bind(&HidServiceLinux::OnPathOpened, base::Passed(&params)));
+#else
+ file_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&HidServiceLinux::OpenOnBlockingThread,
+ base::Passed(&params)));
#endif // defined(OS_CHROMEOS)
-
- file_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&HidServiceLinux::OpenDevice, base::Passed(&params)));
}
HidServiceLinux::~HidServiceLinux() {
@@ -253,26 +246,42 @@ HidServiceLinux::~HidServiceLinux() {
}
#if defined(OS_CHROMEOS)
+
// static
-void HidServiceLinux::OnRequestPathAccessComplete(
+void HidServiceLinux::OnPathOpened(scoped_ptr<ConnectParams> params,
+ dbus::FileDescriptor fd) {
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner =
+ params->file_task_runner;
+ file_task_runner->PostTask(
+ FROM_HERE, base::Bind(&HidServiceLinux::ValidateFdOnBlockingThread,
+ base::Passed(&params), base::Passed(&fd)));
+}
+
+// static
+void HidServiceLinux::ValidateFdOnBlockingThread(
scoped_ptr<ConnectParams> params,
- bool success) {
- if (success) {
- scoped_refptr<base::SingleThreadTaskRunner> file_task_runner =
- params->file_task_runner;
- file_task_runner->PostTask(
- FROM_HERE,
- base::Bind(&HidServiceLinux::OpenDevice, base::Passed(&params)));
+ dbus::FileDescriptor fd) {
+ base::ThreadRestrictions::AssertIOAllowed();
+
+ fd.CheckValidity();
+ if (fd.is_valid()) {
+ params->device_file = base::File(fd.TakeValue());
+ FinishOpen(params.Pass());
} else {
- params->callback.Run(nullptr);
+ HID_LOG(EVENT) << "Permission broker denied access to '"
+ << params->device_info->device_node() << "'.";
+ params->task_runner->PostTask(FROM_HERE,
+ base::Bind(params->callback, nullptr));
}
}
-#endif // defined(OS_CHROMEOS)
+
+#else
// static
-void HidServiceLinux::OpenDevice(scoped_ptr<ConnectParams> params) {
+void HidServiceLinux::OpenOnBlockingThread(scoped_ptr<ConnectParams> params) {
base::ThreadRestrictions::AssertIOAllowed();
scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner;
+
base::FilePath device_path(params->device_info->device_node());
base::File& device_file = params->device_file;
int flags =
@@ -296,26 +305,30 @@ void HidServiceLinux::OpenDevice(scoped_ptr<ConnectParams> params) {
return;
}
- int result = fcntl(device_file.GetPlatformFile(), F_GETFL);
- if (result == -1) {
- HID_PLOG(ERROR) << "Failed to get flags from the device file descriptor";
- task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr));
- return;
- }
+ FinishOpen(params.Pass());
+}
- result = fcntl(device_file.GetPlatformFile(), F_SETFL, result | O_NONBLOCK);
+#endif // defined(OS_CHROMEOS)
+
+// static
+void HidServiceLinux::FinishOpen(scoped_ptr<ConnectParams> params) {
+ base::ThreadRestrictions::AssertIOAllowed();
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner = params->task_runner;
+
+ int result = net::SetNonBlocking(params->device_file.GetPlatformFile());
if (result == -1) {
HID_PLOG(ERROR) << "Failed to set the non-blocking flag on the device fd";
task_runner->PostTask(FROM_HERE, base::Bind(params->callback, nullptr));
return;
}
- task_runner->PostTask(FROM_HERE, base::Bind(&HidServiceLinux::ConnectImpl,
- base::Passed(&params)));
+ task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(&HidServiceLinux::CreateConnection, base::Passed(&params)));
}
// static
-void HidServiceLinux::ConnectImpl(scoped_ptr<ConnectParams> params) {
+void HidServiceLinux::CreateConnection(scoped_ptr<ConnectParams> params) {
DCHECK(params->device_file.IsValid());
params->callback.Run(make_scoped_refptr(
new HidConnectionLinux(params->device_info, params->device_file.Pass(),