1fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry/* 2fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * Copyright (C) 2008 The Android Open Source Project 3fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * All rights reserved. 4fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * 5fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * Redistribution and use in source and binary forms, with or without 6fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * modification, are permitted provided that the following conditions 7fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * are met: 8fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * * Redistributions of source code must retain the above copyright 9fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * notice, this list of conditions and the following disclaimer. 10fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * * Redistributions in binary form must reproduce the above copyright 11fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * notice, this list of conditions and the following disclaimer in 12fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * the documentation and/or other materials provided with the 13fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * distribution. 14fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * 15fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry * SUCH DAMAGE. 27fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry */ 28fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 29e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry#include "system_properties/system_properties.h" 30e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry 31fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <errno.h> 32fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <stdatomic.h> 33fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <stdlib.h> 34fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <string.h> 35fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <sys/stat.h> 36fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <sys/types.h> 37fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <unistd.h> 38fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 398d366a81a361221d872db99d74bbaaa4611bdb82Tom Cherry#include <new> 408d366a81a361221d872db99d74bbaaa4611bdb82Tom Cherry 41fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include <async_safe/log.h> 42fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 43fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include "private/ErrnoRestorer.h" 44fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#include "private/bionic_futex.h" 45e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry 46e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry#include "system_properties/context_node.h" 47e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry#include "system_properties/prop_area.h" 48e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry#include "system_properties/prop_info.h" 49fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 50fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#define SERIAL_DIRTY(serial) ((serial)&1) 51fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry#define SERIAL_VALUE_LEN(serial) ((serial) >> 24) 52fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 53fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherrystatic bool is_dir(const char* pathname) { 54fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry struct stat info; 55fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (stat(pathname, &info) == -1) { 56fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return false; 57fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 58fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return S_ISDIR(info.st_mode); 59fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 60fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 61e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherrybool SystemProperties::Init(const char* filename) { 62fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // This is called from __libc_init_common, and should leave errno at 0 (http://b/37248982). 63fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry ErrnoRestorer errno_restorer; 64fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 65e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (initialized_) { 66ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry contexts_->ResetAccess(); 67e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return true; 68e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry } 69e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry 70e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (strlen(filename) > PROP_FILENAME_MAX) { 71e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return false; 72fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 73e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry strcpy(property_filename_, filename); 74e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry 75e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (is_dir(property_filename_)) { 768be995b6ac69100996e55e1d24c1398a19916436Tom Cherry if (access("/dev/__properties__/property_info", R_OK) == 0) { 77ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry contexts_ = new (contexts_data_) ContextsSerialized(); 78ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry if (!contexts_->Initialize(false, property_filename_, nullptr)) { 79e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return false; 808be995b6ac69100996e55e1d24c1398a19916436Tom Cherry } 818be995b6ac69100996e55e1d24c1398a19916436Tom Cherry } else { 82ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry contexts_ = new (contexts_data_) ContextsSplit(); 83ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry if (!contexts_->Initialize(false, property_filename_, nullptr)) { 84e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return false; 858be995b6ac69100996e55e1d24c1398a19916436Tom Cherry } 86fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 87fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } else { 88ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry contexts_ = new (contexts_data_) ContextsPreSplit(); 89ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry if (!contexts_->Initialize(false, property_filename_, nullptr)) { 90e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return false; 91fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 92fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 93e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry initialized_ = true; 94e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return true; 95fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 96fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 97e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherrybool SystemProperties::AreaInit(const char* filename, bool* fsetxattr_failed) { 98e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (strlen(filename) > PROP_FILENAME_MAX) { 99e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return false; 100fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 101e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry strcpy(property_filename_, filename); 102e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry 103ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry contexts_ = new (contexts_data_) ContextsSerialized(); 104ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry if (!contexts_->Initialize(true, property_filename_, fsetxattr_failed)) { 105e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return false; 106fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 107e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry initialized_ = true; 108e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return true; 109fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 110fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 111e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryuint32_t SystemProperties::AreaSerial() { 112e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (!initialized_) { 113f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry return -1; 114f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry } 115f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry 116ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry prop_area* pa = contexts_->GetSerialPropArea(); 117fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (!pa) { 118fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 119fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 120f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry 121fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // Make sure this read fulfilled before __system_property_serial 122fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return atomic_load_explicit(pa->serial(), memory_order_acquire); 123fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 124fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 125e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryconst prop_info* SystemProperties::Find(const char* name) { 126e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (!initialized_) { 127fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return nullptr; 128fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 129fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 130ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry prop_area* pa = contexts_->GetPropAreaForName(name); 131fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (!pa) { 132fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name); 133fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return nullptr; 134fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 135fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 136fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return pa->find(name); 137fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 138fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 139fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherrystatic bool is_read_only(const char* name) { 140fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return strncmp(name, "ro.", 3) == 0; 141fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 142fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 143e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryint SystemProperties::Read(const prop_info* pi, char* name, char* value) { 144fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry while (true) { 145e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry uint32_t serial = Serial(pi); // acquire semantics 146fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry size_t len = SERIAL_VALUE_LEN(serial); 147fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry memcpy(value, pi->value, len + 1); 148fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // TODO: Fix the synchronization scheme here. 149fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // There is no fully supported way to implement this kind 150fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // of synchronization in C++11, since the memcpy races with 151fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // updates to pi, and the data being accessed is not atomic. 152fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // The following fence is unintuitive, but would be the 153fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // correct one if memcpy used memory_order_relaxed atomic accesses. 154fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // In practice it seems unlikely that the generated code would 155fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // would be any different, so this should be OK. 156fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry atomic_thread_fence(memory_order_acquire); 157fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { 158fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (name != nullptr) { 159fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX); 160fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (namelen >= PROP_NAME_MAX) { 161fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry async_safe_format_log(ANDROID_LOG_ERROR, "libc", 162fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry "The property name length for \"%s\" is >= %d;" 163fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry " please use __system_property_read_callback" 164fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry " to read this property. (the name is truncated to \"%s\")", 165fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry pi->name, PROP_NAME_MAX - 1, name); 166fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 167fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 168fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (is_read_only(pi->name) && pi->is_long()) { 169fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry async_safe_format_log( 170fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry ANDROID_LOG_ERROR, "libc", 171fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry "The property \"%s\" has a value with length %zu that is too large for" 172fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry " __system_property_get()/__system_property_read(); use" 173fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry " __system_property_read_callback() instead.", 174fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry pi->name, strlen(pi->long_value())); 175fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 176fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return len; 177fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 178fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 179fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 180fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 181e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryvoid SystemProperties::ReadCallback(const prop_info* pi, 182e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry void (*callback)(void* cookie, const char* name, 183e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry const char* value, uint32_t serial), 184e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry void* cookie) { 185fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // Read only properties don't need to copy the value to a temporary buffer, since it can never 186fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // change. 187fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (is_read_only(pi->name)) { 188e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry uint32_t serial = Serial(pi); 189fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (pi->is_long()) { 190fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry callback(cookie, pi->name, pi->long_value(), serial); 191fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } else { 192fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry callback(cookie, pi->name, pi->value, serial); 193fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 194fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return; 195fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 196fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 197fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry while (true) { 198e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry uint32_t serial = Serial(pi); // acquire semantics 199fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry size_t len = SERIAL_VALUE_LEN(serial); 200fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry char value_buf[len + 1]; 201fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 202fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry memcpy(value_buf, pi->value, len); 203fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry value_buf[len] = '\0'; 204fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 205e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry // TODO: see todo in Read function 206fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry atomic_thread_fence(memory_order_acquire); 207fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { 208fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry callback(cookie, pi->name, value_buf, serial); 209fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return; 210fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 211fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 212fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 213fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 214e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryint SystemProperties::Get(const char* name, char* value) { 215e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry const prop_info* pi = Find(name); 216fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 217fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (pi != 0) { 218e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry return Read(pi, nullptr, value); 219fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } else { 220fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry value[0] = 0; 221fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return 0; 222fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 223fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 224fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 225e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryint SystemProperties::Update(prop_info* pi, const char* value, unsigned int len) { 226fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (len >= PROP_VALUE_MAX) { 227fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 228fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 229fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 230e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (!initialized_) { 231f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry return -1; 232f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry } 233fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 234ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry prop_area* pa = contexts_->GetSerialPropArea(); 235fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (!pa) { 236fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 237fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 238fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 239fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed); 240fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry serial |= 1; 241fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry atomic_store_explicit(&pi->serial, serial, memory_order_relaxed); 242fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // The memcpy call here also races. Again pretend it 243fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // used memory_order_relaxed atomics, and use the analogous 244fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // counterintuitive fence. 245fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry atomic_thread_fence(memory_order_release); 246fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry strlcpy(pi->value, value, len + 1); 247fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 248fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry atomic_store_explicit(&pi->serial, (len << 24) | ((serial + 1) & 0xffffff), memory_order_release); 249fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry __futex_wake(&pi->serial, INT32_MAX); 250fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 251fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry atomic_store_explicit(pa->serial(), atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1, 252fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry memory_order_release); 253fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry __futex_wake(pa->serial(), INT32_MAX); 254fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 255fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return 0; 256fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 257fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 258e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryint SystemProperties::Add(const char* name, unsigned int namelen, const char* value, 259fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry unsigned int valuelen) { 260fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (valuelen >= PROP_VALUE_MAX && !is_read_only(name)) { 261fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 262fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 263fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 264fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (namelen < 1) { 265fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 266fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 267fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 268e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (!initialized_) { 269fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 270fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 271fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 272ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry prop_area* serial_pa = contexts_->GetSerialPropArea(); 273f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry if (serial_pa == nullptr) { 274f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry return -1; 275f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry } 276fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 277ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry prop_area* pa = contexts_->GetPropAreaForName(name); 278fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (!pa) { 279fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name); 280fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 281fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 282fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 283fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry bool ret = pa->add(name, namelen, value, valuelen); 284fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (!ret) { 285fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 286fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 287fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 288fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // There is only a single mutator, but we want to make sure that 289fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // updates are visible to a reader waiting for the update. 290f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry atomic_store_explicit(serial_pa->serial(), 291f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry atomic_load_explicit(serial_pa->serial(), memory_order_relaxed) + 1, 292f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry memory_order_release); 293f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry __futex_wake(serial_pa->serial(), INT32_MAX); 294fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return 0; 295fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 296fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 297fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry// Wait for non-locked serial, and retrieve it with acquire semantics. 298e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryuint32_t SystemProperties::Serial(const prop_info* pi) { 299fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire); 300fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry while (SERIAL_DIRTY(serial)) { 301fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry __futex_wait(const_cast<_Atomic(uint_least32_t)*>(&pi->serial), serial, nullptr); 302fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry serial = load_const_atomic(&pi->serial, memory_order_acquire); 303fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 304fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return serial; 305fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 306fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 307e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryuint32_t SystemProperties::WaitAny(uint32_t old_serial) { 308fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry uint32_t new_serial; 309e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry Wait(nullptr, old_serial, &new_serial, nullptr); 310fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return new_serial; 311fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 312fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 313e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherrybool SystemProperties::Wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr, 314fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry const timespec* relative_timeout) { 315fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry // Are we waiting on the global serial or a specific serial? 316fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry atomic_uint_least32_t* serial_ptr; 317fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (pi == nullptr) { 318e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (!initialized_) { 319f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry return -1; 320f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry } 321f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry 322ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry prop_area* serial_pa = contexts_->GetSerialPropArea(); 323f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry if (serial_pa == nullptr) { 324f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry return -1; 325f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry } 326f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry 327f76bbf5384c0504b165168f51ccadfb605ccb2afTom Cherry serial_ptr = serial_pa->serial(); 328fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } else { 329fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry serial_ptr = const_cast<atomic_uint_least32_t*>(&pi->serial); 330fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 331fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 332fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry uint32_t new_serial; 333fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry do { 334fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry int rc; 335fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if ((rc = __futex_wait(serial_ptr, old_serial, relative_timeout)) != 0 && rc == -ETIMEDOUT) { 336fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return false; 337fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 338fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry new_serial = load_const_atomic(serial_ptr, memory_order_acquire); 339fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } while (new_serial == old_serial); 340fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 341fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry *new_serial_ptr = new_serial; 342fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return true; 343fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 344fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 345e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryconst prop_info* SystemProperties::FindNth(unsigned n) { 346fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry struct find_nth { 347fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry const uint32_t sought; 348fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry uint32_t current; 349fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry const prop_info* result; 350fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 351fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry explicit find_nth(uint32_t n) : sought(n), current(0), result(nullptr) { 352fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 353fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry static void fn(const prop_info* pi, void* ptr) { 354fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry find_nth* self = reinterpret_cast<find_nth*>(ptr); 355fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry if (self->current++ == self->sought) self->result = pi; 356fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 357fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } state(n); 358e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry Foreach(find_nth::fn, &state); 359fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return state.result; 360fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 361fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 362e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherryint SystemProperties::Foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) { 363e275d6d72db1868056a204e8483a7346a28cb8d6Tom Cherry if (!initialized_) { 364fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return -1; 365fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry } 366fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 367ee8e3dd67c910907115c7cef87be3d898d71a05dTom Cherry contexts_->ForEach(propfn, cookie); 368fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry 369fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry return 0; 370fd44b9f8d89ce4f33ff39d7f340a5ed08029d21cTom Cherry} 371