arc: Filter socket path

BUG=b:219093809
TEST=cros_workon_make --test --board=octopus-arc-r arcvm-mojo-proxy
TEST=tast run arc.Boot.vm

Change-Id: I812080dc2e35c0997cde393bf22b29349dc94826
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3463477
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
Tested-by: Ryo Hashimoto <hashimoto@chromium.org>
Commit-Queue: Ryo Hashimoto <hashimoto@chromium.org>
(cherry picked from commit 15bb9bf953469b8c34d3cae1d1b50b41aea57031)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3476764
Auto-Submit: Ryo Hashimoto <hashimoto@chromium.org>
Reviewed-by: Satoshi Niwa <niwa@chromium.org>
Commit-Queue: Satoshi Niwa <niwa@chromium.org>
diff --git a/arc/vm/mojo_proxy/mojo_proxy.cc b/arc/vm/mojo_proxy/mojo_proxy.cc
index ead8565..7441d25 100644
--- a/arc/vm/mojo_proxy/mojo_proxy.cc
+++ b/arc/vm/mojo_proxy/mojo_proxy.cc
@@ -26,6 +26,9 @@
 namespace arc {
 namespace {
 
+// Path to the ARC bridge socket path.
+constexpr char kArcBridgeSocketPath[] = "/run/chrome/arc_bridge.sock";
+
 std::unique_ptr<LocalFile> CreateFile(
     base::ScopedFD fd,
     arc_proxy::FileDescriptor::Type fd_type,
@@ -68,6 +71,7 @@
 
 MojoProxy::MojoProxy(Delegate* delegate)
     : delegate_(delegate),
+      expected_socket_paths_{base::FilePath(kArcBridgeSocketPath)},
       next_handle_(delegate_->GetType() == Type::SERVER ? 1 : -1),
       next_cookie_(delegate_->GetType() == Type::SERVER ? 1 : -1) {
   // Note: this needs to be initialized after weak_factory_, which is
@@ -351,15 +355,18 @@
 }
 
 bool MojoProxy::OnConnectRequest(arc_proxy::ConnectRequest* request) {
+  base::FilePath path(request->path());
+  if (expected_socket_paths_.count(path) == 0) {
+    LOG(ERROR) << "Unexpected socket path: " << path;
+    return false;
+  }
   arc_proxy::MojoMessage reply;
   auto* response = reply.mutable_connect_response();
-
+  response->set_cookie(request->cookie());
   // Currently, this actually uses only on ArcBridgeService's initial
   // connection establishment, and the request comes from the guest to the host
   // including the |path|.
-  // TODO(hidehiko): Consider allowlist the path which is allowed to access.
-  auto result = ConnectUnixDomainSocket(base::FilePath(request->path()));
-  response->set_cookie(request->cookie());
+  auto result = ConnectUnixDomainSocket(path);
   response->set_error_code(result.first);
   if (result.first == 0) {
     response->set_handle(RegisterFileDescriptor(
diff --git a/arc/vm/mojo_proxy/mojo_proxy.h b/arc/vm/mojo_proxy/mojo_proxy.h
index f5906b0..e6d8f7b 100644
--- a/arc/vm/mojo_proxy/mojo_proxy.h
+++ b/arc/vm/mojo_proxy/mojo_proxy.h
@@ -10,10 +10,12 @@
 #include <deque>
 #include <map>
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
 #include <base/files/file_descriptor_watcher_posix.h>
+#include <base/files/file_path.h>
 #include <base/files/scoped_file.h>
 #include <base/macros.h>
 #include <base/memory/weak_ptr.h>
@@ -21,10 +23,6 @@
 
 #include "arc/vm/mojo_proxy/message.pb.h"
 
-namespace base {
-class FilePath;
-}
-
 namespace arc {
 
 class LocalFile;
@@ -76,6 +74,10 @@
 
   ~MojoProxy();
 
+  void AddExpectedSocketPathForTesting(const base::FilePath& path) {
+    expected_socket_paths_.insert(path);
+  }
+
   // Registers the |fd| whose type is |fd_type| to watch.
   // When |handle| is not 0, associates the specified handle with the given FD.
   // When |handle| is 0, generates a new handle value for the given FD.
@@ -169,6 +171,8 @@
 
   base::Thread blocking_task_thread_{"BlockingThread"};
 
+  std::set<base::FilePath> expected_socket_paths_;
+
   // Map from a |handle| (see message.proto for details) to a file
   // instance wrapping the file descriptor and its watcher.
   // Erasing the entry from this map should close the file descriptor
diff --git a/arc/vm/mojo_proxy/mojo_proxy_test.cc b/arc/vm/mojo_proxy/mojo_proxy_test.cc
index b76c43f..998fec5 100644
--- a/arc/vm/mojo_proxy/mojo_proxy_test.cc
+++ b/arc/vm/mojo_proxy/mojo_proxy_test.cc
@@ -502,6 +502,7 @@
   // Create unix domain socket for testing, which is connected by the following
   // Connect() invocation from client side.
   auto server_sock = CreateUnixDomainSocket(socket_path);
+  server()->AddExpectedSocketPathForTesting(socket_path);
 
   // Try to follow the actual initial connection procedure.
   base::RunLoop run_loop;