Home | History | Annotate | Download | only in init
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "property_service.h"
     18 
     19 #include <ctype.h>
     20 #include <errno.h>
     21 #include <fcntl.h>
     22 #include <inttypes.h>
     23 #include <limits.h>
     24 #include <netinet/in.h>
     25 #include <stdarg.h>
     26 #include <stddef.h>
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <sys/mman.h>
     31 #include <sys/poll.h>
     32 #include <sys/select.h>
     33 #include <sys/types.h>
     34 #include <sys/un.h>
     35 #include <unistd.h>
     36 #include <wchar.h>
     37 
     38 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     39 #include <sys/_system_properties.h>
     40 
     41 #include <memory>
     42 #include <queue>
     43 #include <vector>
     44 
     45 #include <android-base/chrono_utils.h>
     46 #include <android-base/file.h>
     47 #include <android-base/logging.h>
     48 #include <android-base/properties.h>
     49 #include <android-base/stringprintf.h>
     50 #include <android-base/strings.h>
     51 #include <bootimg.h>
     52 #include <fs_mgr.h>
     53 #include <property_info_parser/property_info_parser.h>
     54 #include <property_info_serializer/property_info_serializer.h>
     55 #include <selinux/android.h>
     56 #include <selinux/label.h>
     57 #include <selinux/selinux.h>
     58 
     59 #include "init.h"
     60 #include "persistent_properties.h"
     61 #include "property_type.h"
     62 #include "selinux.h"
     63 #include "subcontext.h"
     64 #include "util.h"
     65 
     66 using namespace std::literals;
     67 
     68 using android::base::GetIntProperty;
     69 using android::base::ReadFileToString;
     70 using android::base::Split;
     71 using android::base::StartsWith;
     72 using android::base::StringPrintf;
     73 using android::base::Timer;
     74 using android::base::Trim;
     75 using android::base::WriteStringToFile;
     76 using android::properties::BuildTrie;
     77 using android::properties::ParsePropertyInfoFile;
     78 using android::properties::PropertyInfoAreaFile;
     79 using android::properties::PropertyInfoEntry;
     80 
     81 #define RECOVERY_MOUNT_POINT "/recovery"
     82 
     83 namespace android {
     84 namespace init {
     85 
     86 static bool persistent_properties_loaded = false;
     87 
     88 static int property_set_fd = -1;
     89 
     90 static PropertyInfoAreaFile property_info_area;
     91 
     92 uint32_t InitPropertySet(const std::string& name, const std::string& value);
     93 
     94 uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet;
     95 
     96 void CreateSerializedPropertyInfo();
     97 
     98 struct PropertyAuditData {
     99     const ucred* cr;
    100     const char* name;
    101 };
    102 
    103 void property_init() {
    104     mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
    105     CreateSerializedPropertyInfo();
    106     if (__system_property_area_init()) {
    107         LOG(FATAL) << "Failed to initialize property area";
    108     }
    109     if (!property_info_area.LoadDefaultPath()) {
    110         LOG(FATAL) << "Failed to load serialized property info file";
    111     }
    112 }
    113 static bool CheckMacPerms(const std::string& name, const char* target_context,
    114                           const char* source_context, const ucred& cr) {
    115     if (!target_context || !source_context) {
    116         return false;
    117     }
    118 
    119     PropertyAuditData audit_data;
    120 
    121     audit_data.name = name.c_str();
    122     audit_data.cr = &cr;
    123 
    124     bool has_access = (selinux_check_access(source_context, target_context, "property_service",
    125                                             "set", &audit_data) == 0);
    126 
    127     return has_access;
    128 }
    129 
    130 static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
    131     size_t valuelen = value.size();
    132 
    133     if (!IsLegalPropertyName(name)) {
    134         *error = "Illegal property name";
    135         return PROP_ERROR_INVALID_NAME;
    136     }
    137 
    138     if (valuelen >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
    139         *error = "Property value too long";
    140         return PROP_ERROR_INVALID_VALUE;
    141     }
    142 
    143     if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
    144         *error = "Value is not a UTF8 encoded string";
    145         return PROP_ERROR_INVALID_VALUE;
    146     }
    147 
    148     prop_info* pi = (prop_info*) __system_property_find(name.c_str());
    149     if (pi != nullptr) {
    150         // ro.* properties are actually "write-once".
    151         if (StartsWith(name, "ro.")) {
    152             *error = "Read-only property was already set";
    153             return PROP_ERROR_READ_ONLY_PROPERTY;
    154         }
    155 
    156         __system_property_update(pi, value.c_str(), valuelen);
    157     } else {
    158         int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
    159         if (rc < 0) {
    160             *error = "__system_property_add failed";
    161             return PROP_ERROR_SET_FAILED;
    162         }
    163     }
    164 
    165     // Don't write properties to disk until after we have read all default
    166     // properties to prevent them from being overwritten by default values.
    167     if (persistent_properties_loaded && StartsWith(name, "persist.")) {
    168         WritePersistentProperty(name, value);
    169     }
    170     property_changed(name, value);
    171     return PROP_SUCCESS;
    172 }
    173 
    174 typedef int (*PropertyAsyncFunc)(const std::string&, const std::string&);
    175 
    176 struct PropertyChildInfo {
    177     pid_t pid;
    178     PropertyAsyncFunc func;
    179     std::string name;
    180     std::string value;
    181 };
    182 
    183 static std::queue<PropertyChildInfo> property_children;
    184 
    185 static void PropertyChildLaunch() {
    186     auto& info = property_children.front();
    187     pid_t pid = fork();
    188     if (pid < 0) {
    189         LOG(ERROR) << "Failed to fork for property_set_async";
    190         while (!property_children.empty()) {
    191             property_children.pop();
    192         }
    193         return;
    194     }
    195     if (pid != 0) {
    196         info.pid = pid;
    197     } else {
    198         if (info.func(info.name, info.value) != 0) {
    199             LOG(ERROR) << "property_set_async(\"" << info.name << "\", \"" << info.value
    200                        << "\") failed";
    201         }
    202         _exit(0);
    203     }
    204 }
    205 
    206 bool PropertyChildReap(pid_t pid) {
    207     if (property_children.empty()) {
    208         return false;
    209     }
    210     auto& info = property_children.front();
    211     if (info.pid != pid) {
    212         return false;
    213     }
    214     std::string error;
    215     if (PropertySet(info.name, info.value, &error) != PROP_SUCCESS) {
    216         LOG(ERROR) << "Failed to set async property " << info.name << " to " << info.value << ": "
    217                    << error;
    218     }
    219     property_children.pop();
    220     if (!property_children.empty()) {
    221         PropertyChildLaunch();
    222     }
    223     return true;
    224 }
    225 
    226 static uint32_t PropertySetAsync(const std::string& name, const std::string& value,
    227                                  PropertyAsyncFunc func, std::string* error) {
    228     if (value.empty()) {
    229         return PropertySet(name, value, error);
    230     }
    231 
    232     PropertyChildInfo info;
    233     info.func = func;
    234     info.name = name;
    235     info.value = value;
    236     property_children.push(info);
    237     if (property_children.size() == 1) {
    238         PropertyChildLaunch();
    239     }
    240     return PROP_SUCCESS;
    241 }
    242 
    243 static int RestoreconRecursiveAsync(const std::string& name, const std::string& value) {
    244     return selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
    245 }
    246 
    247 uint32_t InitPropertySet(const std::string& name, const std::string& value) {
    248     if (StartsWith(name, "ctl.")) {
    249         LOG(ERROR) << "InitPropertySet: Do not set ctl. properties from init; call the Service "
    250                       "functions directly";
    251         return PROP_ERROR_INVALID_NAME;
    252     }
    253     if (name == "selinux.restorecon_recursive") {
    254         LOG(ERROR) << "InitPropertySet: Do not set selinux.restorecon_recursive from init; use the "
    255                       "restorecon builtin directly";
    256         return PROP_ERROR_INVALID_NAME;
    257     }
    258 
    259     uint32_t result = 0;
    260     ucred cr = {.pid = 1, .uid = 0, .gid = 0};
    261     std::string error;
    262     result = HandlePropertySet(name, value, kInitContext.c_str(), cr, &error);
    263     if (result != PROP_SUCCESS) {
    264         LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
    265     }
    266 
    267     return result;
    268 }
    269 
    270 class SocketConnection {
    271   public:
    272     SocketConnection(int socket, const ucred& cred) : socket_(socket), cred_(cred) {}
    273 
    274     ~SocketConnection() { close(socket_); }
    275 
    276     bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) {
    277         return RecvFully(value, sizeof(*value), timeout_ms);
    278     }
    279 
    280     bool RecvChars(char* chars, size_t size, uint32_t* timeout_ms) {
    281         return RecvFully(chars, size, timeout_ms);
    282     }
    283 
    284     bool RecvString(std::string* value, uint32_t* timeout_ms) {
    285         uint32_t len = 0;
    286         if (!RecvUint32(&len, timeout_ms)) {
    287             return false;
    288         }
    289 
    290         if (len == 0) {
    291             *value = "";
    292             return true;
    293         }
    294 
    295         // http://b/35166374: don't allow init to make arbitrarily large allocations.
    296         if (len > 0xffff) {
    297             LOG(ERROR) << "sys_prop: RecvString asked to read huge string: " << len;
    298             errno = ENOMEM;
    299             return false;
    300         }
    301 
    302         std::vector<char> chars(len);
    303         if (!RecvChars(&chars[0], len, timeout_ms)) {
    304             return false;
    305         }
    306 
    307         *value = std::string(&chars[0], len);
    308         return true;
    309     }
    310 
    311     bool SendUint32(uint32_t value) {
    312         int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0));
    313         return result == sizeof(value);
    314     }
    315 
    316     int socket() { return socket_; }
    317 
    318     const ucred& cred() { return cred_; }
    319 
    320     std::string source_context() const {
    321         char* source_context = nullptr;
    322         getpeercon(socket_, &source_context);
    323         std::string result = source_context;
    324         freecon(source_context);
    325         return result;
    326     }
    327 
    328   private:
    329     bool PollIn(uint32_t* timeout_ms) {
    330         struct pollfd ufds[1];
    331         ufds[0].fd = socket_;
    332         ufds[0].events = POLLIN;
    333         ufds[0].revents = 0;
    334         while (*timeout_ms > 0) {
    335             auto start_time = std::chrono::steady_clock::now();
    336             int nr = poll(ufds, 1, *timeout_ms);
    337             auto now = std::chrono::steady_clock::now();
    338             auto time_elapsed =
    339                 std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
    340             uint64_t millis = time_elapsed.count();
    341             *timeout_ms = (millis > *timeout_ms) ? 0 : *timeout_ms - millis;
    342 
    343             if (nr > 0) {
    344                 return true;
    345             }
    346 
    347             if (nr == 0) {
    348                 // Timeout
    349                 break;
    350             }
    351 
    352             if (nr < 0 && errno != EINTR) {
    353                 PLOG(ERROR) << "sys_prop: error waiting for uid " << cred_.uid
    354                             << " to send property message";
    355                 return false;
    356             } else {  // errno == EINTR
    357                 // Timer rounds milliseconds down in case of EINTR we want it to be rounded up
    358                 // to avoid slowing init down by causing EINTR with under millisecond timeout.
    359                 if (*timeout_ms > 0) {
    360                     --(*timeout_ms);
    361                 }
    362             }
    363         }
    364 
    365         LOG(ERROR) << "sys_prop: timeout waiting for uid " << cred_.uid
    366                    << " to send property message.";
    367         return false;
    368     }
    369 
    370     bool RecvFully(void* data_ptr, size_t size, uint32_t* timeout_ms) {
    371         size_t bytes_left = size;
    372         char* data = static_cast<char*>(data_ptr);
    373         while (*timeout_ms > 0 && bytes_left > 0) {
    374             if (!PollIn(timeout_ms)) {
    375                 return false;
    376             }
    377 
    378             int result = TEMP_FAILURE_RETRY(recv(socket_, data, bytes_left, MSG_DONTWAIT));
    379             if (result <= 0) {
    380                 return false;
    381             }
    382 
    383             bytes_left -= result;
    384             data += result;
    385         }
    386 
    387         return bytes_left == 0;
    388     }
    389 
    390     int socket_;
    391     ucred cred_;
    392 
    393     DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection);
    394 };
    395 
    396 bool CheckControlPropertyPerms(const std::string& name, const std::string& value,
    397                                const std::string& source_context, const ucred& cr) {
    398     // We check the legacy method first but these properties are dontaudit, so we only log an audit
    399     // if the newer method fails as well.  We only do this with the legacy ctl. properties.
    400     if (name == "ctl.start" || name == "ctl.stop" || name == "ctl.restart") {
    401         // The legacy permissions model is that ctl. properties have their name ctl.<action> and
    402         // their value is the name of the service to apply that action to.  Permissions for these
    403         // actions are based on the service, so we must create a fake name of ctl.<service> to
    404         // check permissions.
    405         auto control_string_legacy = "ctl." + value;
    406         const char* target_context_legacy = nullptr;
    407         const char* type_legacy = nullptr;
    408         property_info_area->GetPropertyInfo(control_string_legacy.c_str(), &target_context_legacy,
    409                                             &type_legacy);
    410 
    411         if (CheckMacPerms(control_string_legacy, target_context_legacy, source_context.c_str(), cr)) {
    412             return true;
    413         }
    414     }
    415 
    416     auto control_string_full = name + "$" + value;
    417     const char* target_context_full = nullptr;
    418     const char* type_full = nullptr;
    419     property_info_area->GetPropertyInfo(control_string_full.c_str(), &target_context_full,
    420                                         &type_full);
    421 
    422     return CheckMacPerms(control_string_full, target_context_full, source_context.c_str(), cr);
    423 }
    424 
    425 // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
    426 uint32_t HandlePropertySet(const std::string& name, const std::string& value,
    427                            const std::string& source_context, const ucred& cr, std::string* error) {
    428     if (!IsLegalPropertyName(name)) {
    429         *error = "Illegal property name";
    430         return PROP_ERROR_INVALID_NAME;
    431     }
    432 
    433     if (StartsWith(name, "ctl.")) {
    434         if (!CheckControlPropertyPerms(name, value, source_context, cr)) {
    435             *error = StringPrintf("Invalid permissions to perform '%s' on '%s'", name.c_str() + 4,
    436                                   value.c_str());
    437             return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
    438         }
    439 
    440         HandleControlMessage(name.c_str() + 4, value, cr.pid);
    441         return PROP_SUCCESS;
    442     }
    443 
    444     const char* target_context = nullptr;
    445     const char* type = nullptr;
    446     property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
    447 
    448     if (!CheckMacPerms(name, target_context, source_context.c_str(), cr)) {
    449         *error = "SELinux permission check failed";
    450         return PROP_ERROR_PERMISSION_DENIED;
    451     }
    452 
    453     if (type == nullptr || !CheckType(type, value)) {
    454         *error = StringPrintf("Property type check failed, value doesn't match expected type '%s'",
    455                               (type ?: "(null)"));
    456         return PROP_ERROR_INVALID_VALUE;
    457     }
    458 
    459     // sys.powerctl is a special property that is used to make the device reboot.  We want to log
    460     // any process that sets this property to be able to accurately blame the cause of a shutdown.
    461     if (name == "sys.powerctl") {
    462         std::string cmdline_path = StringPrintf("proc/%d/cmdline", cr.pid);
    463         std::string process_cmdline;
    464         std::string process_log_string;
    465         if (ReadFileToString(cmdline_path, &process_cmdline)) {
    466             // Since cmdline is null deliminated, .c_str() conveniently gives us just the process
    467             // path.
    468             process_log_string = StringPrintf(" (%s)", process_cmdline.c_str());
    469         }
    470         LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid
    471                   << process_log_string;
    472     }
    473 
    474     if (name == "selinux.restorecon_recursive") {
    475         return PropertySetAsync(name, value, RestoreconRecursiveAsync, error);
    476     }
    477 
    478     return PropertySet(name, value, error);
    479 }
    480 
    481 static void handle_property_set_fd() {
    482     static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */
    483 
    484     int s = accept4(property_set_fd, nullptr, nullptr, SOCK_CLOEXEC);
    485     if (s == -1) {
    486         return;
    487     }
    488 
    489     ucred cr;
    490     socklen_t cr_size = sizeof(cr);
    491     if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
    492         close(s);
    493         PLOG(ERROR) << "sys_prop: unable to get SO_PEERCRED";
    494         return;
    495     }
    496 
    497     SocketConnection socket(s, cr);
    498     uint32_t timeout_ms = kDefaultSocketTimeout;
    499 
    500     uint32_t cmd = 0;
    501     if (!socket.RecvUint32(&cmd, &timeout_ms)) {
    502         PLOG(ERROR) << "sys_prop: error while reading command from the socket";
    503         socket.SendUint32(PROP_ERROR_READ_CMD);
    504         return;
    505     }
    506 
    507     switch (cmd) {
    508     case PROP_MSG_SETPROP: {
    509         char prop_name[PROP_NAME_MAX];
    510         char prop_value[PROP_VALUE_MAX];
    511 
    512         if (!socket.RecvChars(prop_name, PROP_NAME_MAX, &timeout_ms) ||
    513             !socket.RecvChars(prop_value, PROP_VALUE_MAX, &timeout_ms)) {
    514           PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP): error while reading name/value from the socket";
    515           return;
    516         }
    517 
    518         prop_name[PROP_NAME_MAX-1] = 0;
    519         prop_value[PROP_VALUE_MAX-1] = 0;
    520 
    521         const auto& cr = socket.cred();
    522         std::string error;
    523         uint32_t result =
    524             HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
    525         if (result != PROP_SUCCESS) {
    526             LOG(ERROR) << "Unable to set property '" << prop_name << "' to '" << prop_value
    527                        << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
    528                        << error;
    529         }
    530 
    531         break;
    532       }
    533 
    534     case PROP_MSG_SETPROP2: {
    535         std::string name;
    536         std::string value;
    537         if (!socket.RecvString(&name, &timeout_ms) ||
    538             !socket.RecvString(&value, &timeout_ms)) {
    539           PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP2): error while reading name/value from the socket";
    540           socket.SendUint32(PROP_ERROR_READ_DATA);
    541           return;
    542         }
    543 
    544         const auto& cr = socket.cred();
    545         std::string error;
    546         uint32_t result = HandlePropertySet(name, value, socket.source_context(), cr, &error);
    547         if (result != PROP_SUCCESS) {
    548             LOG(ERROR) << "Unable to set property '" << name << "' to '" << value
    549                        << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
    550                        << error;
    551         }
    552         socket.SendUint32(result);
    553         break;
    554       }
    555 
    556     default:
    557         LOG(ERROR) << "sys_prop: invalid command " << cmd;
    558         socket.SendUint32(PROP_ERROR_INVALID_CMD);
    559         break;
    560     }
    561 }
    562 
    563 static bool load_properties_from_file(const char *, const char *);
    564 
    565 /*
    566  * Filter is used to decide which properties to load: NULL loads all keys,
    567  * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match.
    568  */
    569 static void LoadProperties(char* data, const char* filter, const char* filename) {
    570     char *key, *value, *eol, *sol, *tmp, *fn;
    571     size_t flen = 0;
    572 
    573     const char* context = kInitContext.c_str();
    574     if (SelinuxHasVendorInit()) {
    575         for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
    576             if (StartsWith(filename, path_prefix)) {
    577                 context = secontext;
    578             }
    579         }
    580     }
    581 
    582     if (filter) {
    583         flen = strlen(filter);
    584     }
    585 
    586     sol = data;
    587     while ((eol = strchr(sol, '\n'))) {
    588         key = sol;
    589         *eol++ = 0;
    590         sol = eol;
    591 
    592         while (isspace(*key)) key++;
    593         if (*key == '#') continue;
    594 
    595         tmp = eol - 2;
    596         while ((tmp > key) && isspace(*tmp)) *tmp-- = 0;
    597 
    598         if (!strncmp(key, "import ", 7) && flen == 0) {
    599             fn = key + 7;
    600             while (isspace(*fn)) fn++;
    601 
    602             key = strchr(fn, ' ');
    603             if (key) {
    604                 *key++ = 0;
    605                 while (isspace(*key)) key++;
    606             }
    607 
    608             load_properties_from_file(fn, key);
    609 
    610         } else {
    611             value = strchr(key, '=');
    612             if (!value) continue;
    613             *value++ = 0;
    614 
    615             tmp = value - 2;
    616             while ((tmp > key) && isspace(*tmp)) *tmp-- = 0;
    617 
    618             while (isspace(*value)) value++;
    619 
    620             if (flen > 0) {
    621                 if (filter[flen - 1] == '*') {
    622                     if (strncmp(key, filter, flen - 1)) continue;
    623                 } else {
    624                     if (strcmp(key, filter)) continue;
    625                 }
    626             }
    627 
    628             if (StartsWith(key, "ctl.") || key == "sys.powerctl"s ||
    629                 key == "selinux.restorecon_recursive"s) {
    630                 LOG(ERROR) << "Ignoring disallowed property '" << key
    631                            << "' with special meaning in prop file '" << filename << "'";
    632                 continue;
    633             }
    634 
    635             uint32_t result = 0;
    636             ucred cr = {.pid = 1, .uid = 0, .gid = 0};
    637             std::string error;
    638             result = HandlePropertySet(key, value, context, cr, &error);
    639             if (result != PROP_SUCCESS) {
    640                 LOG(ERROR) << "Unable to set property '" << key << "' to '" << value
    641                            << "' in property file '" << filename << "': " << error;
    642             }
    643         }
    644     }
    645 }
    646 
    647 // Filter is used to decide which properties to load: NULL loads all keys,
    648 // "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match.
    649 static bool load_properties_from_file(const char* filename, const char* filter) {
    650     Timer t;
    651     auto file_contents = ReadFile(filename);
    652     if (!file_contents) {
    653         PLOG(WARNING) << "Couldn't load property file '" << filename
    654                       << "': " << file_contents.error();
    655         return false;
    656     }
    657     file_contents->push_back('\n');
    658 
    659     LoadProperties(file_contents->data(), filter, filename);
    660     LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
    661     return true;
    662 }
    663 
    664 // persist.sys.usb.config values can't be combined on build-time when property
    665 // files are split into each partition.
    666 // So we need to apply the same rule of build/make/tools/post_process_props.py
    667 // on runtime.
    668 static void update_sys_usb_config() {
    669     bool is_debuggable = android::base::GetBoolProperty("ro.debuggable", false);
    670     std::string config = android::base::GetProperty("persist.sys.usb.config", "");
    671     if (config.empty()) {
    672         property_set("persist.sys.usb.config", is_debuggable ? "adb" : "none");
    673     } else if (is_debuggable && config.find("adb") == std::string::npos &&
    674                config.length() + 4 < PROP_VALUE_MAX) {
    675         config.append(",adb");
    676         property_set("persist.sys.usb.config", config);
    677     }
    678 }
    679 
    680 void property_load_boot_defaults() {
    681     if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
    682         // Try recovery path
    683         if (!load_properties_from_file("/prop.default", NULL)) {
    684             // Try legacy path
    685             load_properties_from_file("/default.prop", NULL);
    686         }
    687     }
    688     load_properties_from_file("/product/build.prop", NULL);
    689     load_properties_from_file("/odm/default.prop", NULL);
    690     load_properties_from_file("/vendor/default.prop", NULL);
    691 
    692     update_sys_usb_config();
    693 }
    694 
    695 static void load_override_properties() {
    696     if (ALLOW_LOCAL_PROP_OVERRIDE) {
    697         load_properties_from_file("/data/local.prop", NULL);
    698     }
    699 }
    700 
    701 /* When booting an encrypted system, /data is not mounted when the
    702  * property service is started, so any properties stored there are
    703  * not loaded.  Vold triggers init to load these properties once it
    704  * has mounted /data.
    705  */
    706 void load_persist_props(void) {
    707     // Devices with FDE have load_persist_props called twice; the first time when the temporary
    708     // /data partition is mounted and then again once /data is truly mounted.  We do not want to
    709     // read persistent properties from the temporary /data partition or mark persistent properties
    710     // as having been loaded during the first call, so we return in that case.
    711     std::string crypto_state = android::base::GetProperty("ro.crypto.state", "");
    712     std::string crypto_type = android::base::GetProperty("ro.crypto.type", "");
    713     if (crypto_state == "encrypted" && crypto_type == "block") {
    714         static size_t num_calls = 0;
    715         if (++num_calls == 1) return;
    716     }
    717 
    718     load_override_properties();
    719     /* Read persistent properties after all default values have been loaded. */
    720     auto persistent_properties = LoadPersistentProperties();
    721     for (const auto& persistent_property_record : persistent_properties.properties()) {
    722         property_set(persistent_property_record.name(), persistent_property_record.value());
    723     }
    724     persistent_properties_loaded = true;
    725     property_set("ro.persistent_properties.ready", "true");
    726 }
    727 
    728 void load_recovery_id_prop() {
    729     std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
    730                                                                fs_mgr_free_fstab);
    731     if (!fstab) {
    732         PLOG(ERROR) << "unable to read default fstab";
    733         return;
    734     }
    735 
    736     fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), RECOVERY_MOUNT_POINT);
    737     if (rec == NULL) {
    738         LOG(ERROR) << "/recovery not specified in fstab";
    739         return;
    740     }
    741 
    742     int fd = open(rec->blk_device, O_RDONLY);
    743     if (fd == -1) {
    744         PLOG(ERROR) << "error opening block device " << rec->blk_device;
    745         return;
    746     }
    747 
    748     boot_img_hdr hdr;
    749     if (android::base::ReadFully(fd, &hdr, sizeof(hdr))) {
    750         std::string hex = bytes_to_hex(reinterpret_cast<uint8_t*>(hdr.id), sizeof(hdr.id));
    751         property_set("ro.recovery_id", hex);
    752     } else {
    753         PLOG(ERROR) << "error reading /recovery";
    754     }
    755 
    756     close(fd);
    757 }
    758 
    759 void load_system_props() {
    760     load_properties_from_file("/system/build.prop", NULL);
    761     load_properties_from_file("/odm/build.prop", NULL);
    762     load_properties_from_file("/vendor/build.prop", NULL);
    763     load_properties_from_file("/factory/factory.prop", "ro.*");
    764     load_recovery_id_prop();
    765 }
    766 
    767 static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
    768     auto* d = reinterpret_cast<PropertyAuditData*>(data);
    769 
    770     if (!d || !d->name || !d->cr) {
    771         LOG(ERROR) << "AuditCallback invoked with null data arguments!";
    772         return 0;
    773     }
    774 
    775     snprintf(buf, len, "property=%s pid=%d uid=%d gid=%d", d->name, d->cr->pid, d->cr->uid,
    776              d->cr->gid);
    777     return 0;
    778 }
    779 
    780 bool LoadPropertyInfoFromFile(const std::string& filename,
    781                               std::vector<PropertyInfoEntry>* property_infos) {
    782     auto file_contents = std::string();
    783     if (!ReadFileToString(filename, &file_contents)) {
    784         PLOG(ERROR) << "Could not read properties from '" << filename << "'";
    785         return false;
    786     }
    787 
    788     auto errors = std::vector<std::string>{};
    789     ParsePropertyInfoFile(file_contents, property_infos, &errors);
    790     // Individual parsing errors are reported but do not cause a failed boot, which is what
    791     // returning false would do here.
    792     for (const auto& error : errors) {
    793         LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
    794     }
    795 
    796     return true;
    797 }
    798 
    799 void CreateSerializedPropertyInfo() {
    800     auto property_infos = std::vector<PropertyInfoEntry>();
    801     if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
    802         if (!LoadPropertyInfoFromFile("/system/etc/selinux/plat_property_contexts",
    803                                       &property_infos)) {
    804             return;
    805         }
    806         // Don't check for failure here, so we always have a sane list of properties.
    807         // E.g. In case of recovery, the vendor partition will not have mounted and we
    808         // still need the system / platform properties to function.
    809         if (!LoadPropertyInfoFromFile("/vendor/etc/selinux/vendor_property_contexts",
    810                                       &property_infos)) {
    811             // Fallback to nonplat_* if vendor_* doesn't exist.
    812             LoadPropertyInfoFromFile("/vendor/etc/selinux/nonplat_property_contexts",
    813                                      &property_infos);
    814         }
    815     } else {
    816         if (!LoadPropertyInfoFromFile("/plat_property_contexts", &property_infos)) {
    817             return;
    818         }
    819         if (!LoadPropertyInfoFromFile("/vendor_property_contexts", &property_infos)) {
    820             // Fallback to nonplat_* if vendor_* doesn't exist.
    821             LoadPropertyInfoFromFile("/nonplat_property_contexts", &property_infos);
    822         }
    823     }
    824 
    825     auto serialized_contexts = std::string();
    826     auto error = std::string();
    827     if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "string", &serialized_contexts,
    828                    &error)) {
    829         LOG(ERROR) << "Unable to serialize property contexts: " << error;
    830         return;
    831     }
    832 
    833     constexpr static const char kPropertyInfosPath[] = "/dev/__properties__/property_info";
    834     if (!WriteStringToFile(serialized_contexts, kPropertyInfosPath, 0444, 0, 0, false)) {
    835         PLOG(ERROR) << "Unable to write serialized property infos to file";
    836     }
    837     selinux_android_restorecon(kPropertyInfosPath, 0);
    838 }
    839 
    840 void start_property_service() {
    841     selinux_callback cb;
    842     cb.func_audit = SelinuxAuditCallback;
    843     selinux_set_callback(SELINUX_CB_AUDIT, cb);
    844 
    845     property_set("ro.property_service.version", "2");
    846 
    847     property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
    848                                    false, 0666, 0, 0, nullptr);
    849     if (property_set_fd == -1) {
    850         PLOG(FATAL) << "start_property_service socket creation failed";
    851     }
    852 
    853     listen(property_set_fd, 8);
    854 
    855     register_epoll_handler(property_set_fd, handle_property_set_fd);
    856 }
    857 
    858 }  // namespace init
    859 }  // namespace android
    860