Add UID permission check to update_engine

Test: th
Bug: 302761914
Change-Id: I72a4169b79c70210ae8573abad2e8e181597cfe3
diff --git a/aosp/binder_service_android.cc b/aosp/binder_service_android.cc
index 37df9a5..a89655f 100644
--- a/aosp/binder_service_android.cc
+++ b/aosp/binder_service_android.cc
@@ -22,8 +22,10 @@
 #include <base/logging.h>
 #include <binderwrapper/binder_wrapper.h>
 #include <utils/String8.h>
+#include <android-base/stringprintf.h>
 
 #include "update_engine/aosp/binder_service_android_common.h"
+#include "update_engine/aosp/permission.h"
 
 using android::binder::Status;
 using android::os::IUpdateEngineCallback;
@@ -34,6 +36,7 @@
 
 namespace chromeos_update_engine {
 
+
 BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
     ServiceDelegateAndroidInterface* service_delegate)
     : service_delegate_(service_delegate) {}
@@ -56,6 +59,9 @@
 
 Status BinderUpdateEngineAndroidService::bind(
     const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   // Send an status update on connection (except when no update sent so far).
   // Even though the status update is oneway, it still returns an erroneous
   // status in case of a selinux denial. We should at least check this status
@@ -85,6 +91,9 @@
 
 Status BinderUpdateEngineAndroidService::unbind(
     const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   const android::sp<IBinder>& callback_binder =
       IUpdateEngineCallback::asBinder(callback);
   auto binder_wrapper = android::BinderWrapper::Get();
@@ -99,6 +108,9 @@
     int64_t payload_offset,
     int64_t payload_size,
     const vector<android::String16>& header_kv_pairs) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   const string payload_url{android::String8{url}.c_str()};
   vector<string> str_headers = ToVecString(header_kv_pairs);
 
@@ -115,6 +127,9 @@
     int64_t payload_offset,
     int64_t payload_size,
     const vector<android::String16>& header_kv_pairs) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   vector<string> str_headers = ToVecString(header_kv_pairs);
 
   Error error;
@@ -126,6 +141,9 @@
 }
 
 Status BinderUpdateEngineAndroidService::suspend() {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   Error error;
   if (!service_delegate_->SuspendUpdate(&error))
     return ErrorPtrToStatus(error);
@@ -133,6 +151,9 @@
 }
 
 Status BinderUpdateEngineAndroidService::resume() {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   Error error;
   if (!service_delegate_->ResumeUpdate(&error))
     return ErrorPtrToStatus(error);
@@ -140,6 +161,9 @@
 }
 
 Status BinderUpdateEngineAndroidService::cancel() {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   Error error;
   if (!service_delegate_->CancelUpdate(&error))
     return ErrorPtrToStatus(error);
@@ -147,6 +171,9 @@
 }
 
 Status BinderUpdateEngineAndroidService::resetStatus() {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   Error error;
   if (!service_delegate_->ResetStatus(&error))
     return ErrorPtrToStatus(error);
@@ -155,6 +182,9 @@
 
 Status BinderUpdateEngineAndroidService::setShouldSwitchSlotOnReboot(
     const android::String16& metadata_filename) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   Error error;
   if (!service_delegate_->setShouldSwitchSlotOnReboot(
           android::String8(metadata_filename).c_str(), &error)) {
@@ -164,6 +194,9 @@
 }
 
 Status BinderUpdateEngineAndroidService::resetShouldSwitchSlotOnReboot() {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   Error error;
   if (!service_delegate_->resetShouldSwitchSlotOnReboot(&error)) {
     return ErrorPtrToStatus(error);
@@ -173,6 +206,9 @@
 
 Status BinderUpdateEngineAndroidService::verifyPayloadApplicable(
     const android::String16& metadata_filename, bool* return_value) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   const std::string payload_metadata{
       android::String8{metadata_filename}.c_str()};
   LOG(INFO) << "Received a request of verifying payload metadata in "
@@ -204,6 +240,9 @@
     const android::String16& metadata_filename,
     const vector<android::String16>& header_kv_pairs,
     int64_t* return_value) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   const std::string payload_metadata{
       android::String8{metadata_filename}.c_str()};
   vector<string> str_headers = ToVecString(header_kv_pairs);
@@ -246,6 +285,9 @@
 
 Status BinderUpdateEngineAndroidService::cleanupSuccessfulUpdate(
     const android::sp<IUpdateEngineCallback>& callback) {
+  if (const auto status = CheckCallingUid(); !status.isOk()) {
+    return status;
+  }
   Error error;
   service_delegate_->CleanupSuccessfulUpdate(
       std::make_unique<CleanupSuccessfulUpdateCallback>(callback), &error);
diff --git a/aosp/permission.cc b/aosp/permission.cc
new file mode 100644
index 0000000..6f13b03
--- /dev/null
+++ b/aosp/permission.cc
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <update_engine/aosp/permission.h>
+
+#include <array>
+#include <algorithm>
+#include <android-base/stringprintf.h>
+#include <android-base/logging.h>
+
+namespace chromeos_update_engine {
+
+android::binder::Status CheckCallingUid() {
+  const auto calling_uid = android::BinderWrapper::Get()->GetCallingUid();
+  if (!Contains(kAllowedUids, calling_uid)) {
+    LOG(ERROR) << "Calling UID " << calling_uid
+               << " is not allowed to access update_engine APIs";
+    auto message =
+        android::base::StringPrintf("UID %d is not allowed", calling_uid);
+    return android::binder::Status::fromExceptionCode(
+        android::binder::Status::EX_SECURITY,
+        android::String8(message.c_str()));
+  }
+  return android::binder::Status::ok();
+}
+
+}  // namespace chromeos_update_engine
diff --git a/aosp/permission.h b/aosp/permission.h
new file mode 100644
index 0000000..46eaad0
--- /dev/null
+++ b/aosp/permission.h
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_COMMON_PERMISSION_H_
+#define UPDATE_ENGINE_COMMON_PERMISSION_H_
+
+#include <binder/Status.h>
+#include <binderwrapper/binder_wrapper.h>
+#ifdef __ANDROID__
+#include <array>
+#include <private/android_filesystem_config.h>
+#include <algorithm>
+
+namespace chromeos_update_engine {
+static constexpr std::array<uid_t, 2> kAllowedUids = {AID_ROOT, AID_SYSTEM};
+
+template <typename Container, typename T>
+bool Contains(const Container& container, const T& t) {
+  return std::find(container.begin(), container.end(), t) != container.end();
+}
+
+android::binder::Status CheckCallingUid();
+
+}  // namespace chromeos_update_engine
+#endif  // __ANDROID__
+
+#endif  // UPDATE_ENGINE_COMMON_PERMISSION_H_