diff options
author | reillyg <reillyg@chromium.org> | 2015-07-10 14:36:10 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-10 21:37:06 +0000 |
commit | e6aead1fa5623666c4e5cd78ce17e1935ee769b1 (patch) | |
tree | 3f5963630f62ab1136fb4a5dfb55e5a8fd695a40 /device/hid/hid_service_linux.cc | |
parent | 047ad603c025597829bb6e0482752ad95b2e431c (diff) | |
download | chromium_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.cc | 91 |
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(¶ms))); - } 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(¶ms))); +#else + file_task_runner_->PostTask(FROM_HERE, + base::Bind(&HidServiceLinux::OpenOnBlockingThread, + base::Passed(¶ms))); #endif // defined(OS_CHROMEOS) - - file_task_runner_->PostTask( - FROM_HERE, - base::Bind(&HidServiceLinux::OpenDevice, base::Passed(¶ms))); } 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(¶ms), 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(¶ms))); + 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(¶ms))); + task_runner->PostTask( + FROM_HERE, + base::Bind(&HidServiceLinux::CreateConnection, base::Passed(¶ms))); } // 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(), |