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