179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry/*
279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * Copyright (C) 2017 The Android Open Source Project
379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * All rights reserved.
479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *
579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * Redistribution and use in source and binary forms, with or without
679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * modification, are permitted provided that the following conditions
779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * are met:
879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *  * Redistributions of source code must retain the above copyright
979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *    notice, this list of conditions and the following disclaimer.
1079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *  * Redistributions in binary form must reproduce the above copyright
1179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *    notice, this list of conditions and the following disclaimer in
1279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *    the documentation and/or other materials provided with the
1379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *    distribution.
1479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry *
1579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry * SUCH DAMAGE.
2779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry */
2879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
29e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry#include "system_properties/contexts_serialized.h"
3079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
3179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry#include <fcntl.h>
32e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry#include <limits.h>
3379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry#include <sys/mman.h>
3479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry#include <sys/stat.h>
3579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry#include <sys/types.h>
3679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
3779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry#include <new>
3879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
3979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry#include <async_safe/log.h>
4079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
4179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry#include "private/bionic_prctl.h"
42e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry#include "system_properties/system_properties.h"
4379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
4479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherrybool ContextsSerialized::InitializeContextNodes() {
4579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  auto num_context_nodes = property_info_area_file_->num_contexts();
4679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  auto context_nodes_mmap_size = sizeof(ContextNode) * num_context_nodes;
4779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  // We want to avoid malloc in system properties, so we take an anonymous map instead (b/31659220).
4879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  void* const map_result = mmap(nullptr, context_nodes_mmap_size, PROT_READ | PROT_WRITE,
4979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry                                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
5079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (map_result == MAP_FAILED) {
5179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    return false;
5279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
5379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
5479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_result, context_nodes_mmap_size,
5579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry        "System property context nodes");
5679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
5779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  context_nodes_ = reinterpret_cast<ContextNode*>(map_result);
5879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  num_context_nodes_ = num_context_nodes;
5979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  context_nodes_mmap_size_ = context_nodes_mmap_size;
6079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
6179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  for (size_t i = 0; i < num_context_nodes; ++i) {
62e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry    new (&context_nodes_[i]) ContextNode(property_info_area_file_->context(i), filename_);
6379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
6479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
6579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  return true;
6679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
6779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
6879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherrybool ContextsSerialized::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed) {
6979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  char filename[PROP_FILENAME_MAX];
70e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial", filename_);
7179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (len < 0 || len > PROP_FILENAME_MAX) {
7279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    serial_prop_area_ = nullptr;
7379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    return false;
7479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
7579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
7679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (access_rw) {
7779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    serial_prop_area_ =
7879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry        prop_area::map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
7979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  } else {
8079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    serial_prop_area_ = prop_area::map_prop_area(filename);
8179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
8279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  return serial_prop_area_;
8379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
8479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
8579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherrybool ContextsSerialized::InitializeProperties() {
8679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (!property_info_area_file_.LoadDefaultPath()) {
8779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    return false;
8879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
8979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
9079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (!InitializeContextNodes()) {
9179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    FreeAndUnmap();
9279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    return false;
9379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
9479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
9579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  return true;
9679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
9779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
98e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherrybool ContextsSerialized::Initialize(bool writable, const char* filename, bool* fsetxattr_failed) {
99e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry  filename_ = filename;
10079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (!InitializeProperties()) {
10179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    return false;
10279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
10379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
10479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (writable) {
105e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry    mkdir(filename_, S_IRWXU | S_IXGRP | S_IXOTH);
10679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    bool open_failed = false;
107e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry    if (fsetxattr_failed) {
108e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry      *fsetxattr_failed = false;
109e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry    }
11079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
11179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    for (size_t i = 0; i < num_context_nodes_; ++i) {
112e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry      if (!context_nodes_[i].Open(true, fsetxattr_failed)) {
11379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry        open_failed = true;
11479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry      }
11579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    }
116e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry    if (open_failed || !MapSerialPropertyArea(true, fsetxattr_failed)) {
11779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry      FreeAndUnmap();
11879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry      return false;
11979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    }
12079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  } else {
12179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    if (!MapSerialPropertyArea(false, nullptr)) {
12279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry      FreeAndUnmap();
12379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry      return false;
12479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    }
12579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
12679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  return true;
12779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
12879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
12979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherryprop_area* ContextsSerialized::GetPropAreaForName(const char* name) {
13079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  uint32_t index;
13179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  property_info_area_file_->GetPropertyInfoIndexes(name, &index, nullptr);
13279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (index == ~0u || index >= num_context_nodes_) {
13379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Could not find context for property \"%s\"",
13479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry                          name);
13579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    return nullptr;
13679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
13779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  auto* context_node = &context_nodes_[index];
13879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (!context_node->pa()) {
13979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    // We explicitly do not check no_access_ in this case because unlike the
14079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    // case of foreach(), we want to generate an selinux audit for each
14179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    // non-permitted property access in this function.
14279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    context_node->Open(false, nullptr);
14379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
14479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  return context_node->pa();
14579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
14679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
14779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherryvoid ContextsSerialized::ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
14879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  for (size_t i = 0; i < num_context_nodes_; ++i) {
14979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    if (context_nodes_[i].CheckAccessAndOpen()) {
15079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry      context_nodes_[i].pa()->foreach (propfn, cookie);
15179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    }
15279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
15379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
15479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
15579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherryvoid ContextsSerialized::ResetAccess() {
15679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  for (size_t i = 0; i < num_context_nodes_; ++i) {
15779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    context_nodes_[i].ResetAccess();
15879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
15979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
16079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry
16179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherryvoid ContextsSerialized::FreeAndUnmap() {
16279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  property_info_area_file_.Reset();
16379b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  if (context_nodes_ != nullptr) {
16479b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    for (size_t i = 0; i < num_context_nodes_; ++i) {
16579b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry      context_nodes_[i].Unmap();
16679b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    }
16779b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    munmap(context_nodes_, context_nodes_mmap_size_);
16879b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry    context_nodes_ = nullptr;
16979b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  }
17079b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  prop_area::unmap_prop_area(&serial_prop_area_);
17179b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry  serial_prop_area_ = nullptr;
17279b724ca5a33e5dff7c2530b2649648021c1258dTom Cherry}
173