Restrict setting platform properties from vendor .prop files

We should only allow vendor-init-settable properties to be set from
.prop files on /vendor and /odm.

Bug: 73905119
Test: test on walleye that disallowed properties are rejected
Change-Id: I2a5d244fdc71060ddda3e3d87442e831e6b97831
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 624780f..95ef35c 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -59,8 +59,11 @@
 #include "init.h"
 #include "persistent_properties.h"
 #include "property_type.h"
+#include "subcontext.h"
 #include "util.h"
 
+using namespace std::literals;
+
 using android::base::ReadFileToString;
 using android::base::Split;
 using android::base::StartsWith;
@@ -533,11 +536,17 @@
  * Filter is used to decide which properties to load: NULL loads all keys,
  * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match.
  */
-static void load_properties(char *data, const char *filter)
-{
+static void LoadProperties(char* data, const char* filter, const char* filename) {
     char *key, *value, *eol, *sol, *tmp, *fn;
     size_t flen = 0;
 
+    const char* context = kInitContext.c_str();
+    for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
+        if (StartsWith(filename, path_prefix)) {
+            context = secontext;
+        }
+    }
+
     if (filter) {
         flen = strlen(filter);
     }
@@ -584,7 +593,21 @@
                 }
             }
 
-            property_set(key, value);
+            if (StartsWith(key, "ctl.") || key == "sys.powerctl"s ||
+                key == "selinux.restorecon_recursive"s) {
+                LOG(ERROR) << "Ignoring disallowed property '" << key
+                           << "' with special meaning in prop file '" << filename << "'";
+                continue;
+            }
+
+            uint32_t result = 0;
+            ucred cr = {.pid = 1, .uid = 0, .gid = 0};
+            std::string error;
+            result = HandlePropertySet(key, value, context, cr, &error);
+            if (result != PROP_SUCCESS) {
+                LOG(ERROR) << "Unable to set property '" << key << "' to '" << value
+                           << "' in property file '" << filename << "': " << error;
+            }
         }
     }
 }
@@ -600,7 +623,8 @@
         return false;
     }
     file_contents->push_back('\n');
-    load_properties(file_contents->data(), filter);
+
+    LoadProperties(file_contents->data(), filter, filename);
     LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
     return true;
 }
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 762492c..c1846f7 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -49,6 +49,11 @@
 const std::string kInitContext = "u:r:init:s0";
 const std::string kVendorContext = "u:r:vendor_init:s0";
 
+const char* const paths_and_secontexts[2][2] = {
+    {"/vendor", kVendorContext.c_str()},
+    {"/odm", kVendorContext.c_str()},
+};
+
 namespace {
 
 constexpr size_t kBufferSize = 4096;
@@ -349,9 +354,6 @@
 static std::vector<Subcontext> subcontexts;
 
 std::vector<Subcontext>* InitializeSubcontexts() {
-    static const char* const paths_and_secontexts[][2] = {
-        {"/vendor", kVendorContext.c_str()},
-    };
     for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
         subcontexts.emplace_back(path_prefix, secontext);
     }
diff --git a/init/subcontext.h b/init/subcontext.h
index 5601b80..22d7d43 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -33,6 +33,7 @@
 
 extern const std::string kInitContext;
 extern const std::string kVendorContext;
+extern const char* const paths_and_secontexts[2][2];
 
 class Subcontext {
   public: