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