Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c44522e authored by Ian Coolidge's avatar Ian Coolidge
Browse files

Provide --android-ipc-socket-suffix.

This allows Android init to create a socket
for the service, and have consolidated access control.

Android init creates the socket and passes the FD through
an environment variable, so we must use OSI to decode it.

Bug: 22807533
Change-Id: I7ec0a14b8f3b44277ce99faad68623d6691f7863
parent 74f8af2b
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -92,9 +92,9 @@ bool Daemon::Init() {


  ipc_manager_.reset(new ipc::IPCManager(core_stack_.get()));
  ipc_manager_.reset(new ipc::IPCManager(core_stack_.get()));


  // If an IPC socket path was given, initialize the UNIX domain socket based
  // If an IPC socket path was given, initialize IPC with it.
  // IPC layer.
  if ((!settings_->create_ipc_socket_path().empty() ||
  if (!settings_->ipc_socket_path().empty() &&
       !settings_->android_ipc_socket_suffix().empty()) &&
      !ipc_manager_->Start(ipc::IPCManager::TYPE_UNIX)) {
      !ipc_manager_->Start(ipc::IPCManager::TYPE_UNIX)) {
    LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
    LOG(ERROR) << "Failed to set up UNIX domain-socket IPCManager";
    return false;
    return false;
+46 −24
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@


#include <base/bind.h>
#include <base/bind.h>


#include "osi/include/socket_utils/sockets.h"
#include "service/daemon.h"
#include "service/daemon.h"
#include "service/ipc/unix_ipc_host.h"
#include "service/ipc/unix_ipc_host.h"
#include "service/settings.h"
#include "service/settings.h"
@@ -39,9 +40,14 @@ IPCHandlerUnix::~IPCHandlerUnix() {
bool IPCHandlerUnix::Run() {
bool IPCHandlerUnix::Run() {
  CHECK(!running_);
  CHECK(!running_);


  const std::string& android_suffix =
      bluetooth::Daemon::Get()->settings()->android_ipc_socket_suffix();
  const base::FilePath& path =
  const base::FilePath& path =
      bluetooth::Daemon::Get()->settings()->ipc_socket_path();
      bluetooth::Daemon::Get()->settings()->create_ipc_socket_path();
  if (path.empty()) {

  // Both flags cannot be set at the same time.
  CHECK(android_suffix.empty() || path.empty());
  if (android_suffix.empty() && path.empty()) {
    LOG(ERROR) << "No domain socket path provided";
    LOG(ERROR) << "No domain socket path provided";
    return false;
    return false;
  }
  }
@@ -49,6 +55,17 @@ bool IPCHandlerUnix::Run() {
  CHECK(base::MessageLoop::current());  // An origin event loop is required.
  CHECK(base::MessageLoop::current());  // An origin event loop is required.
  origin_task_runner_ = base::MessageLoop::current()->task_runner();
  origin_task_runner_ = base::MessageLoop::current()->task_runner();


  if (!android_suffix.empty()) {
    int server_fd = osi_android_get_control_socket(android_suffix.c_str());
    if (server_fd == -1) {
      LOG(ERROR) << "Unable to get Android socket from: " << android_suffix;
      return false;
    }
    LOG(INFO) << "Binding to Android server socket:" << android_suffix;
    socket_.reset(server_fd);
  } else {
    LOG(INFO) << "Creating a Unix domain socket:" << path.value();

    // TODO(armansito): This is opens the door to potentially unlinking files in
    // TODO(armansito): This is opens the door to potentially unlinking files in
    // the current directory that we're not supposed to. For now we will have an
    // the current directory that we're not supposed to. For now we will have an
    // assumption that the daemon runs in a sandbox but we should generally do
    // assumption that the daemon runs in a sandbox but we should generally do
@@ -66,14 +83,19 @@ bool IPCHandlerUnix::Run() {
    struct sockaddr_un address;
    struct sockaddr_un address;
    memset(&address, 0, sizeof(address));
    memset(&address, 0, sizeof(address));
    address.sun_family = AF_UNIX;
    address.sun_family = AF_UNIX;
  strncpy(address.sun_path, path.value().c_str(), sizeof(address.sun_path) - 1);
    strncpy(address.sun_path, path.value().c_str(),
  if (bind(server_socket.get(), (struct sockaddr*)&address,
            sizeof(address.sun_path) - 1);
           sizeof(address)) < 0) {
    if (bind(server_socket.get(), (struct sockaddr*)&address, sizeof(address)) <
        0) {
      LOG(ERROR) << "Failed to bind IPC socket to address: " << strerror(errno);
      LOG(ERROR) << "Failed to bind IPC socket to address: " << strerror(errno);
      return false;
      return false;
    }
    }


    socket_.swap(server_socket);
    socket_.swap(server_socket);
  }

  CHECK(socket_.is_valid());

  running_ = true;  // Set this here before launching the thread.
  running_ = true;  // Set this here before launching the thread.


  // Start an IO thread and post the listening task.
  // Start an IO thread and post the listening task.
+22 −6
Original line number Original line Diff line number Diff line
@@ -35,23 +35,39 @@ bool Settings::Init() {
  const auto& switches = command_line->GetSwitches();
  const auto& switches = command_line->GetSwitches();


  for (const auto& iter : switches) {
  for (const auto& iter : switches) {
    if (iter.first == switches::kIPCSocketPath) {
    if (iter.first == switches::kCreateIPCSocketPath) {
      // kIPCSocketPath: An optional argument that initializes an IPC socket
      // kCreateIPCSocketPath: An optional argument that initializes an IPC
      // path for IPC. If this is not present, the daemon will default to Binder
      // socket path for IPC.
      // for the IPC mechanism.
      base::FilePath path(iter.second);
      base::FilePath path(iter.second);
      if (path.empty() || path.EndsWithSeparator()) {
      if (path.empty() || path.EndsWithSeparator()) {
        LOG(ERROR) << "Invalid IPC socket path";
        LOG(ERROR) << "Invalid IPC create socket path";
        return false;
        return false;
      }
      }


      ipc_socket_path_ = path;
      create_ipc_socket_path_ = path;
    } else if (iter.first == switches::kAndroidIPCSocketSuffix) {
      // kAndroidIPCSocketSuffix: An optional argument used to express
      // a socket that Android init created for us. We bind to this.
      const std::string& suffix = iter.second;
      if (suffix.empty()) {
        LOG(ERROR) << "Invalid Android socket suffix";
        return false;
      }

      android_ipc_socket_suffix_ = suffix;
    } else {
    } else {
      LOG(ERROR) << "Unexpected command-line switches found";
      LOG(ERROR) << "Unexpected command-line switches found";
      return false;
      return false;
    }
    }
  }
  }


  // Two IPC methods/paths were provided.
  if (!android_ipc_socket_suffix_.empty() &&
      !create_ipc_socket_path_.empty()) {
    LOG(ERROR) << "Too many IPC methods provided";
    return false;
  }

  // The daemon has no arguments
  // The daemon has no arguments
  if (command_line->GetArgs().size()) {
  if (command_line->GetArgs().size()) {
    LOG(ERROR) << "Unexpected command-line arguments found";
    LOG(ERROR) << "Unexpected command-line arguments found";
+11 −7
Original line number Original line Diff line number Diff line
@@ -42,17 +42,21 @@ class Settings {
  // if there is an error, e.g. if the parameters/switches are malformed.
  // if there is an error, e.g. if the parameters/switches are malformed.
  bool Init();
  bool Init();


  // Path to the unix domain socket for Bluetooth IPC. On Android, this needs to
  // If Android init created a server socket for the daemon,
  // match the init provided socket domain prefix. Outside Android, this will be
  // we can retrieve it through this suffix.
  // the path for the traditional Unix domain socket that the daemon will
  const std::string& android_ipc_socket_suffix() const {
  // create.
    return android_ipc_socket_suffix_;
  const base::FilePath& ipc_socket_path() const {
  }
    return ipc_socket_path_;

  // Path to create a Unix domain socket server for Bluetooth IPC.
  const base::FilePath& create_ipc_socket_path() const {
    return create_ipc_socket_path_;
  }
  }


 private:
 private:
  bool initialized_;
  bool initialized_;
  base::FilePath ipc_socket_path_;
  std::string android_ipc_socket_suffix_;
  base::FilePath create_ipc_socket_path_;


  DISALLOW_COPY_AND_ASSIGN(Settings);
  DISALLOW_COPY_AND_ASSIGN(Settings);
};
};
+6 −2
Original line number Original line Diff line number Diff line
@@ -24,14 +24,18 @@ namespace switches {
// List of command-line switches used by the daemon.
// List of command-line switches used by the daemon.
const char kHelpLong[] = "help";
const char kHelpLong[] = "help";
const char kHelpShort[] = "h";
const char kHelpShort[] = "h";
const char kIPCSocketPath[] = "ipc-socket";
const char kAndroidIPCSocketSuffix[] = "android-ipc-socket-suffix";
const char kCreateIPCSocketPath[] = "create-ipc-socket";


const char kHelpMessage[] =
const char kHelpMessage[] =
    "\nBluetooth System Service\n"
    "\nBluetooth System Service\n"
    "\n"
    "\n"
    "Usage:\n"
    "Usage:\n"
    "\t--help,-h\tShow this help message\n"
    "\t--help,-h\tShow this help message\n"
    "\t--ipc-socket\tSocket path used for domain socket based IPC";
    "\t--android-ipc-socket-suffix\tSuffix of socket created by Android init. "
    "Mutually exclusive with --create-ipc-socket.\n"
    "\t--create-ipc-socket\tSocket path created for Unix domain socket based "
    "IPC. Mutually exclusive with --android-ipc-socket-suffix.";


}  // namespace switches
}  // namespace switches
}  // namespace bluetooth
}  // namespace bluetooth
Loading