Reland 'Check /dev/binder access before calling defaultServiceManager()'

Vendor processes do not have access to /dev/binder. Calling
defaultServiceManager() without RW permission will crash the process
with error message "Binder driver could not be opened.  Terminating."

Normally, VNDK version of libcutils.so would not have the codepath of
ashmemd. However, on non-VNDK this codepath is exercised.

We check if the current process has permissions to /dev/binder before
calling defaultServiceManager() to avoid crashing. The calling code in
libcutils.so handles inability to connect ashmemd correctly. It will
fall back to opening /dev/ashmem directly. Vendor code should already
have permissions for that.

This SELinux denial shows which permissions need to be checked for:
avc: denied { read write } for name="binder" dev="tmpfs" ino=5570
scontext=u:r:hal_sensors_default:s0 tcontext=u:object_r:binder_device:s0
tclass=chr_file permissive=0

Note that the problem only manifests on non-VNDK devices.

Bug: 129073672
Test: ashmemd_test
Test: VtsHalSensorsV1_0TargetTest
--gtest_filter=SensorsHidlTest.AccelerometerAshmemDirectReportOperationNormal
Test: atest CtsOsTestCases:android.os.cts.SeccompTest#testIsolatedServicePolicy
Change-Id: I23bef7986298811ce2bd84c3fdc9c9e22837c368
diff --git a/ashmemd_client.cpp b/ashmemd_client.cpp
index 3380209..a9041a0 100644
--- a/ashmemd_client.cpp
+++ b/ashmemd_client.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 #include <android/ashmemd/IAshmemDeviceService.h>
 #include <binder/IServiceManager.h>
+#include <cutils/android_filesystem_config.h>
 
 using android::IBinder;
 using android::IServiceManager;
@@ -27,7 +28,25 @@
 namespace android {
 namespace ashmemd {
 
+static bool checkBinderAccess() {
+    // Isolated apps are potentially subject to seccomp policy that restricts use of access()
+    // (b/129483782). However, apps always have access to binder, so return true.
+    auto uid = getuid() % AID_USER;
+    if (AID_ISOLATED_START <= uid && uid <= AID_ISOLATED_END) {
+        return true;
+    }
+    if (access("/dev/binder", R_OK | W_OK) == 0) {
+        return true;
+    }
+    return false;
+}
+
 sp<IAshmemDeviceService> getAshmemService() {
+    // Calls to defaultServiceManager() crash the process if it doesn't have appropriate
+    // binder permissions. Check these permissions proactively.
+    if (!checkBinderAccess()) {
+        return nullptr;
+    }
     sp<IServiceManager> sm = android::defaultServiceManager();
     sp<IBinder> binder = sm->checkService(String16("ashmem_device_service"));
     return interface_cast<IAshmemDeviceService>(binder);