Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60fe0152 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 4551672 from a621cc15 to pi-release

Change-Id: I8b43af37313446590249a3dca99ea463c6bd5679
parents 0c75fadc a621cc15
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ cc_library_static {
        "persistent_properties.cpp",
        "persistent_properties.proto",
        "property_service.cpp",
        "property_type.cpp",
        "security.cpp",
        "selinux.cpp",
        "service.cpp",
@@ -178,6 +179,7 @@ cc_test {
        "init_test.cpp",
        "persistent_properties_test.cpp",
        "property_service_test.cpp",
        "property_type_test.cpp",
        "result_test.cpp",
        "rlimit_parser_test.cpp",
        "service_test.cpp",
+24 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <android-base/properties.h>
#include <android-base/strings.h>

#include "stable_properties.h"
#include "util.h"

using android::base::Join;
@@ -134,6 +135,25 @@ void Action::ExecuteCommand(const Command& command) const {
    }
}

static bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
    static bool enabled =
        android::base::GetBoolProperty("ro.actionable_compatible_property.enabled", false);

    if (subcontext == nullptr || !enabled) {
        return true;
    }

    if (kExportedActionableProperties.count(prop_name) == 1) {
        return true;
    }
    for (const auto& prefix : kPartnerPrefixes) {
        if (android::base::StartsWith(prop_name, prefix)) {
            return true;
        }
    }
    return false;
}

Result<Success> Action::ParsePropertyTrigger(const std::string& trigger) {
    const static std::string prop_str("property:");
    std::string prop_name(trigger.substr(prop_str.length()));
@@ -145,6 +165,10 @@ Result<Success> Action::ParsePropertyTrigger(const std::string& trigger) {
    std::string prop_value(prop_name.substr(equal_pos + 1));
    prop_name.erase(equal_pos);

    if (!IsActionableProperty(subcontext_, prop_name)) {
        return Error() << "unexported property tigger found: " << prop_name;
    }

    if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) {
        return Error() << "multiple property triggers found for same property";
    }
+57 −59
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@

#include "init.h"
#include "persistent_properties.h"
#include "property_type.h"
#include "util.h"

using android::base::ReadFileToString;
@@ -95,14 +96,9 @@ void property_init() {
        LOG(FATAL) << "Failed to load serialized property info file";
    }
}
static bool check_mac_perms(const std::string& name, char* sctx, struct ucred* cr) {
    if (!sctx) {
      return false;
    }

    const char* target_context = nullptr;
    property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);
    if (target_context == nullptr) {
static bool CheckMacPerms(const std::string& name, const char* target_context,
                          const char* source_context, struct ucred* cr) {
    if (!target_context || !source_context) {
        return false;
    }

@@ -111,29 +107,12 @@ static bool check_mac_perms(const std::string& name, char* sctx, struct ucred* c
    audit_data.name = name.c_str();
    audit_data.cr = cr;

    bool has_access =
        (selinux_check_access(sctx, target_context, "property_service", "set", &audit_data) == 0);
    bool has_access = (selinux_check_access(source_context, target_context, "property_service",
                                            "set", &audit_data) == 0);

    return has_access;
}

static int check_control_mac_perms(const char *name, char *sctx, struct ucred *cr)
{
    /*
     *  Create a name prefix out of ctl.<service name>
     *  The new prefix allows the use of the existing
     *  property service backend labeling while avoiding
     *  mislabels based on true property prefixes.
     */
    char ctl_name[PROP_VALUE_MAX+4];
    int ret = snprintf(ctl_name, sizeof(ctl_name), "ctl.%s", name);

    if (ret < 0 || (size_t) ret >= sizeof(ctl_name))
        return 0;

    return check_mac_perms(ctl_name, sctx, cr);
}

bool is_legal_property_name(const std::string& name) {
    size_t namelen = name.size();

@@ -422,25 +401,51 @@ static void handle_property_set(SocketConnection& socket,
  struct ucred cr = socket.cred();
  char* source_ctx = nullptr;
  getpeercon(socket.socket(), &source_ctx);
  std::string source_context = source_ctx;
  freecon(source_ctx);

  if (StartsWith(name, "ctl.")) {
    if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) {
      // ctl. properties have their name ctl.<action> and their value is the name of the service to
      // apply that action to.  Permissions for these actions are based on the service, so we must
      // create a fake name of ctl.<service> to check permissions.
      auto control_string = "ctl." + value;
      const char* target_context = nullptr;
      const char* type = nullptr;
      property_info_area->GetPropertyInfo(control_string.c_str(), &target_context, &type);
      if (!CheckMacPerms(control_string, target_context, source_context.c_str(), &cr)) {
          LOG(ERROR) << "sys_prop(" << cmd_name << "): Unable to " << (name.c_str() + 4)
                     << " service ctl [" << value << "]"
                     << " uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid;
          if (!legacy_protocol) {
              socket.SendUint32(PROP_ERROR_HANDLE_CONTROL_MESSAGE);
          }
          return;
      }

      handle_control_message(name.c_str() + 4, value.c_str());
      if (!legacy_protocol) {
          socket.SendUint32(PROP_SUCCESS);
      }
  } else {
      LOG(ERROR) << "sys_prop(" << cmd_name << "): Unable to " << (name.c_str() + 4)
                 << " service ctl [" << value << "]"
                 << " uid:" << cr.uid
                 << " gid:" << cr.gid
                 << " pid:" << cr.pid;
      const char* target_context = nullptr;
      const char* type = nullptr;
      property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
      if (!CheckMacPerms(name, target_context, source_context.c_str(), &cr)) {
          LOG(ERROR) << "sys_prop(" << cmd_name << "): permission denied uid:" << cr.uid
                     << " name:" << name;
          if (!legacy_protocol) {
        socket.SendUint32(PROP_ERROR_HANDLE_CONTROL_MESSAGE);
              socket.SendUint32(PROP_ERROR_PERMISSION_DENIED);
          }
          return;
      }
      if (type == nullptr || !CheckType(type, value)) {
          LOG(ERROR) << "sys_prop(" << cmd_name << "): type check failed, type: '"
                     << (type ?: "(null)") << "' value: '" << value << "'";
          if (!legacy_protocol) {
              socket.SendUint32(PROP_ERROR_INVALID_VALUE);
          }
          return;
      }
  } else {
    if (check_mac_perms(name, source_ctx, &cr)) {
      // sys.powerctl is a special property that is used to make the device reboot.  We want to log
      // any process that sets this property to be able to accurately blame the cause of a shutdown.
      if (name == "sys.powerctl") {
@@ -459,17 +464,9 @@ static void handle_property_set(SocketConnection& socket,
      if (!legacy_protocol) {
          socket.SendUint32(result);
      }
    } else {
      LOG(ERROR) << "sys_prop(" << cmd_name << "): permission denied uid:" << cr.uid << " name:" << name;
      if (!legacy_protocol) {
        socket.SendUint32(PROP_ERROR_PERMISSION_DENIED);
      }
  }
}

  freecon(source_ctx);
}

static void handle_property_set_fd() {
    static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */

@@ -764,9 +761,10 @@ void CreateSerializedPropertyInfo() {
        }
        LoadPropertyInfoFromFile("/nonplat_property_contexts", &property_infos);
    }

    auto serialized_contexts = std::string();
    auto error = std::string();
    if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "\\s*", &serialized_contexts,
    if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "string", &serialized_contexts,
                   &error)) {
        LOG(ERROR) << "Unable to serialize property contexts: " << error;
        return;

init/property_type.cpp

0 → 100644
+81 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2017 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 "property_type.h"

#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>

using android::base::ParseDouble;
using android::base::ParseInt;
using android::base::ParseUint;
using android::base::Split;

namespace android {
namespace init {

bool CheckType(const std::string& type_string, const std::string& value) {
    auto type_strings = Split(type_string, " ");
    if (type_strings.empty()) {
        return false;
    }
    auto type = type_strings[0];

    if (type == "string") {
        return true;
    }
    if (type == "bool") {
        return value == "true" || value == "false" || value == "1" || value == "0";
    }
    if (type == "int") {
        int64_t parsed;
        return ParseInt(value, &parsed);
    }
    if (type == "uint") {
        uint64_t parsed;
        if (value.empty() || value.front() == '-') {
            return false;
        }
        return ParseUint(value, &parsed);
    }
    if (type == "double") {
        double parsed;
        return ParseDouble(value.c_str(), &parsed);
    }
    if (type == "size") {
        auto it = value.begin();
        while (it != value.end() && isdigit(*it)) {
            it++;
        }
        if (it == value.begin() || it == value.end() || (*it != 'g' && *it != 'k' && *it != 'm')) {
            return false;
        }
        it++;
        return it == value.end();
    }
    if (type == "enum") {
        for (auto it = std::next(type_strings.begin()); it != type_strings.end(); ++it) {
            if (*it == value) {
                return true;
            }
        }
    }
    return false;
}

}  // namespace init
}  // namespace android

init/property_type.h

0 → 100644
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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 _INIT_PROPERTY_TYPE_H
#define _INIT_PROPERTY_TYPE_H

#include <string>

namespace android {
namespace init {

bool CheckType(const std::string& type_string, const std::string& value);

}  // namespace init
}  // namespace android

#endif
Loading