Make vendor_init check SELinux before setting properties

Finishing a TODO from vendor_init, check SELinux permissions before
setting properties in vendor_init.

Bug: 62875318
Test: N/A
Change-Id: I3cb6abadd2613ae083705cc6b9c970587b6c6b19
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index be754da..f3b643a 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -27,9 +27,13 @@
 #include <selinux/android.h>
 
 #include "action.h"
+#include "property_service.h"
 #include "selinux.h"
 #include "util.h"
 
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
+
 using android::base::GetExecutablePath;
 using android::base::Join;
 using android::base::Socketpair;
@@ -75,6 +79,13 @@
     return Success();
 }
 
+std::vector<std::pair<std::string, std::string>> properties_to_set;
+
+uint32_t SubcontextPropertySet(const std::string& name, const std::string& value) {
+    properties_to_set.emplace_back(name, value);
+    return PROP_SUCCESS;
+}
+
 class SubcontextProcess {
   public:
     SubcontextProcess(const KeywordFunctionMap* function_map, std::string context, int init_fd)
@@ -108,6 +119,14 @@
         result = RunBuiltinFunction(map_result->second, args, context_);
     }
 
+    for (const auto& [name, value] : properties_to_set) {
+        auto property = reply->add_properties_to_set();
+        property->set_name(name);
+        property->set_value(value);
+    }
+
+    properties_to_set.clear();
+
     if (result) {
         reply->set_success(true);
     } else {
@@ -186,6 +205,9 @@
     auto init_fd = std::atoi(argv[3]);
 
     SelabelInitialize();
+
+    property_set = SubcontextPropertySet;
+
     auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
     subcontext_process.MainLoop();
     return 0;
@@ -257,10 +279,6 @@
         Restart();
         return Error() << "Unable to parse message from subcontext";
     }
-    if (subcontext_reply.reply_case() == SubcontextReply::kFailure) {
-        auto& failure = subcontext_reply.failure();
-        return ResultError(failure.error_string(), failure.error_errno());
-    }
     return subcontext_reply;
 }
 
@@ -275,6 +293,16 @@
         return subcontext_reply.error();
     }
 
+    for (const auto& property : subcontext_reply->properties_to_set()) {
+        ucred cr = {.pid = pid_, .uid = 0, .gid = 0};
+        HandlePropertySet(property.name(), property.value(), context_, cr);
+    }
+
+    if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
+        auto& failure = subcontext_reply->failure();
+        return ResultError(failure.error_string(), failure.error_errno());
+    }
+
     if (subcontext_reply->reply_case() != SubcontextReply::kSuccess) {
         return Error() << "Unexpected message type from subcontext: "
                        << subcontext_reply->reply_case();
@@ -294,6 +322,11 @@
         return subcontext_reply.error();
     }
 
+    if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
+        auto& failure = subcontext_reply->failure();
+        return ResultError(failure.error_string(), failure.error_errno());
+    }
+
     if (subcontext_reply->reply_case() != SubcontextReply::kExpandArgsReply) {
         return Error() << "Unexpected message type from subcontext: "
                        << subcontext_reply->reply_case();