Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <ctype.h>
     30 #include <errno.h>
     31 #include <fcntl.h>
     32 #include <poll.h>
     33 #include <stdatomic.h>
     34 #include <stdbool.h>
     35 #include <stddef.h>
     36 #include <stdint.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include <unistd.h>
     40 #include <new>
     41 
     42 #include <linux/xattr.h>
     43 #include <netinet/in.h>
     44 #include <sys/mman.h>
     45 #include <sys/select.h>
     46 #include <sys/socket.h>
     47 #include <sys/stat.h>
     48 #include <sys/types.h>
     49 #include <sys/uio.h>
     50 #include <sys/un.h>
     51 #include <sys/xattr.h>
     52 
     53 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     54 #include <sys/_system_properties.h>
     55 #include <sys/system_properties.h>
     56 
     57 #include "private/ErrnoRestorer.h"
     58 #include "private/bionic_futex.h"
     59 #include "private/bionic_lock.h"
     60 #include "private/bionic_macros.h"
     61 #include "private/bionic_sdk_version.h"
     62 #include "private/libc_logging.h"
     63 
     64 static constexpr int PROP_FILENAME_MAX = 1024;
     65 
     66 static constexpr uint32_t PROP_AREA_MAGIC = 0x504f5250;
     67 static constexpr uint32_t PROP_AREA_VERSION = 0xfc6ed0ab;
     68 
     69 static constexpr size_t PA_SIZE = 128 * 1024;
     70 
     71 #define SERIAL_DIRTY(serial) ((serial)&1)
     72 #define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
     73 
     74 static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
     75 static const char* kServiceVersionPropertyName = "ro.property_service.version";
     76 
     77 /*
     78  * Properties are stored in a hybrid trie/binary tree structure.
     79  * Each property's name is delimited at '.' characters, and the tokens are put
     80  * into a trie structure.  Siblings at each level of the trie are stored in a
     81  * binary tree.  For instance, "ro.secure"="1" could be stored as follows:
     82  *
     83  * +-----+   children    +----+   children    +--------+
     84  * |     |-------------->| ro |-------------->| secure |
     85  * +-----+               +----+               +--------+
     86  *                       /    \                /   |
     87  *                 left /      \ right   left /    |  prop   +===========+
     88  *                     v        v            v     +-------->| ro.secure |
     89  *                  +-----+   +-----+     +-----+            +-----------+
     90  *                  | net |   | sys |     | com |            |     1     |
     91  *                  +-----+   +-----+     +-----+            +===========+
     92  */
     93 
     94 // Represents a node in the trie.
     95 struct prop_bt {
     96   uint32_t namelen;
     97 
     98   // The property trie is updated only by the init process (single threaded) which provides
     99   // property service. And it can be read by multiple threads at the same time.
    100   // As the property trie is not protected by locks, we use atomic_uint_least32_t types for the
    101   // left, right, children "pointers" in the trie node. To make sure readers who see the
    102   // change of "pointers" can also notice the change of prop_bt structure contents pointed by
    103   // the "pointers", we always use release-consume ordering pair when accessing these "pointers".
    104 
    105   // prop "points" to prop_info structure if there is a propery associated with the trie node.
    106   // Its situation is similar to the left, right, children "pointers". So we use
    107   // atomic_uint_least32_t and release-consume ordering to protect it as well.
    108 
    109   // We should also avoid rereading these fields redundantly, since not
    110   // all processor implementations ensure that multiple loads from the
    111   // same field are carried out in the right order.
    112   atomic_uint_least32_t prop;
    113 
    114   atomic_uint_least32_t left;
    115   atomic_uint_least32_t right;
    116 
    117   atomic_uint_least32_t children;
    118 
    119   char name[0];
    120 
    121   prop_bt(const char* name, const uint32_t name_length) {
    122     this->namelen = name_length;
    123     memcpy(this->name, name, name_length);
    124     this->name[name_length] = '\0';
    125   }
    126 
    127  private:
    128   DISALLOW_COPY_AND_ASSIGN(prop_bt);
    129 };
    130 
    131 class prop_area {
    132  public:
    133   prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
    134     atomic_init(&serial_, 0);
    135     memset(reserved_, 0, sizeof(reserved_));
    136     // Allocate enough space for the root node.
    137     bytes_used_ = sizeof(prop_bt);
    138   }
    139 
    140   const prop_info* find(const char* name);
    141   bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
    142 
    143   bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
    144 
    145   atomic_uint_least32_t* serial() {
    146     return &serial_;
    147   }
    148   uint32_t magic() const {
    149     return magic_;
    150   }
    151   uint32_t version() const {
    152     return version_;
    153   }
    154 
    155  private:
    156   void* allocate_obj(const size_t size, uint_least32_t* const off);
    157   prop_bt* new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off);
    158   prop_info* new_prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen,
    159                            uint_least32_t* const off);
    160   void* to_prop_obj(uint_least32_t off);
    161   prop_bt* to_prop_bt(atomic_uint_least32_t* off_p);
    162   prop_info* to_prop_info(atomic_uint_least32_t* off_p);
    163 
    164   prop_bt* root_node();
    165 
    166   prop_bt* find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen, bool alloc_if_needed);
    167 
    168   const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen,
    169                                  const char* value, uint32_t valuelen, bool alloc_if_needed);
    170 
    171   bool foreach_property(prop_bt* const trie, void (*propfn)(const prop_info* pi, void* cookie),
    172                         void* cookie);
    173 
    174   uint32_t bytes_used_;
    175   atomic_uint_least32_t serial_;
    176   uint32_t magic_;
    177   uint32_t version_;
    178   uint32_t reserved_[28];
    179   char data_[0];
    180 
    181   DISALLOW_COPY_AND_ASSIGN(prop_area);
    182 };
    183 
    184 struct prop_info {
    185   atomic_uint_least32_t serial;
    186   // we need to keep this buffer around because the property
    187   // value can be modified whereas name is constant.
    188   char value[PROP_VALUE_MAX];
    189   char name[0];
    190 
    191   prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen) {
    192     memcpy(this->name, name, namelen);
    193     this->name[namelen] = '\0';
    194     atomic_init(&this->serial, valuelen << 24);
    195     memcpy(this->value, value, valuelen);
    196     this->value[valuelen] = '\0';
    197   }
    198 
    199  private:
    200   DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
    201 };
    202 
    203 // This is public because it was exposed in the NDK. As of 2017-01, ~60 apps reference this symbol.
    204 prop_area* __system_property_area__ = nullptr;
    205 
    206 static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME;
    207 static size_t pa_data_size;
    208 static size_t pa_size;
    209 static bool initialized = false;
    210 
    211 static prop_area* map_prop_area_rw(const char* filename, const char* context,
    212                                    bool* fsetxattr_failed) {
    213   /* dev is a tmpfs that we can use to carve a shared workspace
    214    * out of, so let's do that...
    215    */
    216   const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
    217 
    218   if (fd < 0) {
    219     if (errno == EACCES) {
    220       /* for consistency with the case where the process has already
    221        * mapped the page in and segfaults when trying to write to it
    222        */
    223       abort();
    224     }
    225     return nullptr;
    226   }
    227 
    228   if (context) {
    229     if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
    230       __libc_format_log(ANDROID_LOG_ERROR, "libc",
    231                         "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
    232       /*
    233        * fsetxattr() will fail during system properties tests due to selinux policy.
    234        * We do not want to create a custom policy for the tester, so we will continue in
    235        * this function but set a flag that an error has occurred.
    236        * Init, which is the only daemon that should ever call this function will abort
    237        * when this error occurs.
    238        * Otherwise, the tester will ignore it and continue, albeit without any selinux
    239        * property separation.
    240        */
    241       if (fsetxattr_failed) {
    242         *fsetxattr_failed = true;
    243       }
    244     }
    245   }
    246 
    247   if (ftruncate(fd, PA_SIZE) < 0) {
    248     close(fd);
    249     return nullptr;
    250   }
    251 
    252   pa_size = PA_SIZE;
    253   pa_data_size = pa_size - sizeof(prop_area);
    254 
    255   void* const memory_area = mmap(nullptr, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    256   if (memory_area == MAP_FAILED) {
    257     close(fd);
    258     return nullptr;
    259   }
    260 
    261   prop_area* pa = new (memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION);
    262 
    263   close(fd);
    264   return pa;
    265 }
    266 
    267 static prop_area* map_fd_ro(const int fd) {
    268   struct stat fd_stat;
    269   if (fstat(fd, &fd_stat) < 0) {
    270     return nullptr;
    271   }
    272 
    273   if ((fd_stat.st_uid != 0) || (fd_stat.st_gid != 0) ||
    274       ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) ||
    275       (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area)))) {
    276     return nullptr;
    277   }
    278 
    279   pa_size = fd_stat.st_size;
    280   pa_data_size = pa_size - sizeof(prop_area);
    281 
    282   void* const map_result = mmap(nullptr, pa_size, PROT_READ, MAP_SHARED, fd, 0);
    283   if (map_result == MAP_FAILED) {
    284     return nullptr;
    285   }
    286 
    287   prop_area* pa = reinterpret_cast<prop_area*>(map_result);
    288   if ((pa->magic() != PROP_AREA_MAGIC) || (pa->version() != PROP_AREA_VERSION)) {
    289     munmap(pa, pa_size);
    290     return nullptr;
    291   }
    292 
    293   return pa;
    294 }
    295 
    296 static prop_area* map_prop_area(const char* filename) {
    297   int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
    298   if (fd == -1) return nullptr;
    299 
    300   prop_area* map_result = map_fd_ro(fd);
    301   close(fd);
    302 
    303   return map_result;
    304 }
    305 
    306 void* prop_area::allocate_obj(const size_t size, uint_least32_t* const off) {
    307   const size_t aligned = BIONIC_ALIGN(size, sizeof(uint_least32_t));
    308   if (bytes_used_ + aligned > pa_data_size) {
    309     return nullptr;
    310   }
    311 
    312   *off = bytes_used_;
    313   bytes_used_ += aligned;
    314   return data_ + *off;
    315 }
    316 
    317 prop_bt* prop_area::new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off) {
    318   uint_least32_t new_offset;
    319   void* const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
    320   if (p != nullptr) {
    321     prop_bt* bt = new (p) prop_bt(name, namelen);
    322     *off = new_offset;
    323     return bt;
    324   }
    325 
    326   return nullptr;
    327 }
    328 
    329 prop_info* prop_area::new_prop_info(const char* name, uint32_t namelen, const char* value,
    330                                     uint32_t valuelen, uint_least32_t* const off) {
    331   uint_least32_t new_offset;
    332   void* const p = allocate_obj(sizeof(prop_info) + namelen + 1, &new_offset);
    333   if (p != nullptr) {
    334     prop_info* info = new (p) prop_info(name, namelen, value, valuelen);
    335     *off = new_offset;
    336     return info;
    337   }
    338 
    339   return nullptr;
    340 }
    341 
    342 void* prop_area::to_prop_obj(uint_least32_t off) {
    343   if (off > pa_data_size) return nullptr;
    344 
    345   return (data_ + off);
    346 }
    347 
    348 inline prop_bt* prop_area::to_prop_bt(atomic_uint_least32_t* off_p) {
    349   uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
    350   return reinterpret_cast<prop_bt*>(to_prop_obj(off));
    351 }
    352 
    353 inline prop_info* prop_area::to_prop_info(atomic_uint_least32_t* off_p) {
    354   uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
    355   return reinterpret_cast<prop_info*>(to_prop_obj(off));
    356 }
    357 
    358 inline prop_bt* prop_area::root_node() {
    359   return reinterpret_cast<prop_bt*>(to_prop_obj(0));
    360 }
    361 
    362 static int cmp_prop_name(const char* one, uint32_t one_len, const char* two, uint32_t two_len) {
    363   if (one_len < two_len)
    364     return -1;
    365   else if (one_len > two_len)
    366     return 1;
    367   else
    368     return strncmp(one, two, one_len);
    369 }
    370 
    371 prop_bt* prop_area::find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen,
    372                                  bool alloc_if_needed) {
    373   prop_bt* current = bt;
    374   while (true) {
    375     if (!current) {
    376       return nullptr;
    377     }
    378 
    379     const int ret = cmp_prop_name(name, namelen, current->name, current->namelen);
    380     if (ret == 0) {
    381       return current;
    382     }
    383 
    384     if (ret < 0) {
    385       uint_least32_t left_offset = atomic_load_explicit(&current->left, memory_order_relaxed);
    386       if (left_offset != 0) {
    387         current = to_prop_bt(&current->left);
    388       } else {
    389         if (!alloc_if_needed) {
    390           return nullptr;
    391         }
    392 
    393         uint_least32_t new_offset;
    394         prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
    395         if (new_bt) {
    396           atomic_store_explicit(&current->left, new_offset, memory_order_release);
    397         }
    398         return new_bt;
    399       }
    400     } else {
    401       uint_least32_t right_offset = atomic_load_explicit(&current->right, memory_order_relaxed);
    402       if (right_offset != 0) {
    403         current = to_prop_bt(&current->right);
    404       } else {
    405         if (!alloc_if_needed) {
    406           return nullptr;
    407         }
    408 
    409         uint_least32_t new_offset;
    410         prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset);
    411         if (new_bt) {
    412           atomic_store_explicit(&current->right, new_offset, memory_order_release);
    413         }
    414         return new_bt;
    415       }
    416     }
    417   }
    418 }
    419 
    420 const prop_info* prop_area::find_property(prop_bt* const trie, const char* name, uint32_t namelen,
    421                                           const char* value, uint32_t valuelen,
    422                                           bool alloc_if_needed) {
    423   if (!trie) return nullptr;
    424 
    425   const char* remaining_name = name;
    426   prop_bt* current = trie;
    427   while (true) {
    428     const char* sep = strchr(remaining_name, '.');
    429     const bool want_subtree = (sep != nullptr);
    430     const uint32_t substr_size = (want_subtree) ? sep - remaining_name : strlen(remaining_name);
    431 
    432     if (!substr_size) {
    433       return nullptr;
    434     }
    435 
    436     prop_bt* root = nullptr;
    437     uint_least32_t children_offset = atomic_load_explicit(&current->children, memory_order_relaxed);
    438     if (children_offset != 0) {
    439       root = to_prop_bt(&current->children);
    440     } else if (alloc_if_needed) {
    441       uint_least32_t new_offset;
    442       root = new_prop_bt(remaining_name, substr_size, &new_offset);
    443       if (root) {
    444         atomic_store_explicit(&current->children, new_offset, memory_order_release);
    445       }
    446     }
    447 
    448     if (!root) {
    449       return nullptr;
    450     }
    451 
    452     current = find_prop_bt(root, remaining_name, substr_size, alloc_if_needed);
    453     if (!current) {
    454       return nullptr;
    455     }
    456 
    457     if (!want_subtree) break;
    458 
    459     remaining_name = sep + 1;
    460   }
    461 
    462   uint_least32_t prop_offset = atomic_load_explicit(&current->prop, memory_order_relaxed);
    463   if (prop_offset != 0) {
    464     return to_prop_info(&current->prop);
    465   } else if (alloc_if_needed) {
    466     uint_least32_t new_offset;
    467     prop_info* new_info = new_prop_info(name, namelen, value, valuelen, &new_offset);
    468     if (new_info) {
    469       atomic_store_explicit(&current->prop, new_offset, memory_order_release);
    470     }
    471 
    472     return new_info;
    473   } else {
    474     return nullptr;
    475   }
    476 }
    477 
    478 class PropertyServiceConnection {
    479  public:
    480   PropertyServiceConnection() : last_error_(0) {
    481     socket_ = ::socket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
    482     if (socket_ == -1) {
    483       last_error_ = errno;
    484       return;
    485     }
    486 
    487     const size_t namelen = strlen(property_service_socket);
    488     sockaddr_un addr;
    489     memset(&addr, 0, sizeof(addr));
    490     strlcpy(addr.sun_path, property_service_socket, sizeof(addr.sun_path));
    491     addr.sun_family = AF_LOCAL;
    492     socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
    493 
    494     if (TEMP_FAILURE_RETRY(connect(socket_, reinterpret_cast<sockaddr*>(&addr), alen)) == -1) {
    495       close(socket_);
    496       socket_ = -1;
    497       last_error_ = errno;
    498     }
    499   }
    500 
    501   bool IsValid() {
    502     return socket_ != -1;
    503   }
    504 
    505   int GetLastError() {
    506     return last_error_;
    507   }
    508 
    509   bool RecvInt32(int32_t* value) {
    510     int result = TEMP_FAILURE_RETRY(recv(socket_, value, sizeof(*value), MSG_WAITALL));
    511     return CheckSendRecvResult(result, sizeof(*value));
    512   }
    513 
    514   int socket() {
    515     return socket_;
    516   }
    517 
    518   ~PropertyServiceConnection() {
    519     if (socket_ != -1) {
    520       close(socket_);
    521     }
    522   }
    523 
    524  private:
    525   bool CheckSendRecvResult(int result, int expected_len) {
    526     if (result == -1) {
    527       last_error_ = errno;
    528     } else if (result != expected_len) {
    529       last_error_ = -1;
    530     } else {
    531       last_error_ = 0;
    532     }
    533 
    534     return last_error_ == 0;
    535   }
    536 
    537   int socket_;
    538   int last_error_;
    539 
    540   friend class SocketWriter;
    541 };
    542 
    543 class SocketWriter {
    544  public:
    545   explicit SocketWriter(PropertyServiceConnection* connection)
    546       : connection_(connection), iov_index_(0), uint_buf_index_(0)
    547   {}
    548 
    549   SocketWriter& WriteUint32(uint32_t value) {
    550     CHECK(uint_buf_index_ < kUintBufSize);
    551     CHECK(iov_index_ < kIovSize);
    552     uint32_t* ptr = uint_buf_ + uint_buf_index_;
    553     uint_buf_[uint_buf_index_++] = value;
    554     iov_[iov_index_].iov_base = ptr;
    555     iov_[iov_index_].iov_len = sizeof(*ptr);
    556     ++iov_index_;
    557     return *this;
    558   }
    559 
    560   SocketWriter& WriteString(const char* value) {
    561     uint32_t valuelen = strlen(value);
    562     WriteUint32(valuelen);
    563     if (valuelen == 0) {
    564       return *this;
    565     }
    566 
    567     CHECK(iov_index_ < kIovSize);
    568     iov_[iov_index_].iov_base = const_cast<char*>(value);
    569     iov_[iov_index_].iov_len = valuelen;
    570     ++iov_index_;
    571 
    572     return *this;
    573   }
    574 
    575   bool Send() {
    576     if (!connection_->IsValid()) {
    577       return false;
    578     }
    579 
    580     if (writev(connection_->socket(), iov_, iov_index_) == -1) {
    581       connection_->last_error_ = errno;
    582       return false;
    583     }
    584 
    585     iov_index_ = uint_buf_index_ = 0;
    586     return true;
    587   }
    588 
    589  private:
    590   static constexpr size_t kUintBufSize = 8;
    591   static constexpr size_t kIovSize = 8;
    592 
    593   PropertyServiceConnection* connection_;
    594   iovec iov_[kIovSize];
    595   size_t iov_index_;
    596   uint32_t uint_buf_[kUintBufSize];
    597   size_t uint_buf_index_;
    598 
    599   DISALLOW_IMPLICIT_CONSTRUCTORS(SocketWriter);
    600 };
    601 
    602 struct prop_msg {
    603   unsigned cmd;
    604   char name[PROP_NAME_MAX];
    605   char value[PROP_VALUE_MAX];
    606 };
    607 
    608 static int send_prop_msg(const prop_msg* msg) {
    609   PropertyServiceConnection connection;
    610   if (!connection.IsValid()) {
    611     return connection.GetLastError();
    612   }
    613 
    614   int result = -1;
    615   int s = connection.socket();
    616 
    617   const int num_bytes = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
    618   if (num_bytes == sizeof(prop_msg)) {
    619     // We successfully wrote to the property server but now we
    620     // wait for the property server to finish its work.  It
    621     // acknowledges its completion by closing the socket so we
    622     // poll here (on nothing), waiting for the socket to close.
    623     // If you 'adb shell setprop foo bar' you'll see the POLLHUP
    624     // once the socket closes.  Out of paranoia we cap our poll
    625     // at 250 ms.
    626     pollfd pollfds[1];
    627     pollfds[0].fd = s;
    628     pollfds[0].events = 0;
    629     const int poll_result = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */));
    630     if (poll_result == 1 && (pollfds[0].revents & POLLHUP) != 0) {
    631       result = 0;
    632     } else {
    633       // Ignore the timeout and treat it like a success anyway.
    634       // The init process is single-threaded and its property
    635       // service is sometimes slow to respond (perhaps it's off
    636       // starting a child process or something) and thus this
    637       // times out and the caller thinks it failed, even though
    638       // it's still getting around to it.  So we fake it here,
    639       // mostly for ctl.* properties, but we do try and wait 250
    640       // ms so callers who do read-after-write can reliably see
    641       // what they've written.  Most of the time.
    642       // TODO: fix the system properties design.
    643       __libc_format_log(ANDROID_LOG_WARN, "libc",
    644                         "Property service has timed out while trying to set \"%s\" to \"%s\"",
    645                         msg->name, msg->value);
    646       result = 0;
    647     }
    648   }
    649 
    650   return result;
    651 }
    652 
    653 bool prop_area::foreach_property(prop_bt* const trie,
    654                                  void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
    655   if (!trie) return false;
    656 
    657   uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
    658   if (left_offset != 0) {
    659     const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
    660     if (err < 0) return false;
    661   }
    662   uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
    663   if (prop_offset != 0) {
    664     prop_info* info = to_prop_info(&trie->prop);
    665     if (!info) return false;
    666     propfn(info, cookie);
    667   }
    668   uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
    669   if (children_offset != 0) {
    670     const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
    671     if (err < 0) return false;
    672   }
    673   uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
    674   if (right_offset != 0) {
    675     const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
    676     if (err < 0) return false;
    677   }
    678 
    679   return true;
    680 }
    681 
    682 const prop_info* prop_area::find(const char* name) {
    683   return find_property(root_node(), name, strlen(name), nullptr, 0, false);
    684 }
    685 
    686 bool prop_area::add(const char* name, unsigned int namelen, const char* value,
    687                     unsigned int valuelen) {
    688   return find_property(root_node(), name, namelen, value, valuelen, true);
    689 }
    690 
    691 bool prop_area::foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
    692   return foreach_property(root_node(), propfn, cookie);
    693 }
    694 
    695 class context_node {
    696  public:
    697   context_node(context_node* next, const char* context, prop_area* pa)
    698       : next(next), context_(strdup(context)), pa_(pa), no_access_(false) {
    699     lock_.init(false);
    700   }
    701   ~context_node() {
    702     unmap();
    703     free(context_);
    704   }
    705   bool open(bool access_rw, bool* fsetxattr_failed);
    706   bool check_access_and_open();
    707   void reset_access();
    708 
    709   const char* context() const {
    710     return context_;
    711   }
    712   prop_area* pa() {
    713     return pa_;
    714   }
    715 
    716   context_node* next;
    717 
    718  private:
    719   bool check_access();
    720   void unmap();
    721 
    722   Lock lock_;
    723   char* context_;
    724   prop_area* pa_;
    725   bool no_access_;
    726 };
    727 
    728 struct prefix_node {
    729   prefix_node(struct prefix_node* next, const char* prefix, context_node* context)
    730       : prefix(strdup(prefix)), prefix_len(strlen(prefix)), context(context), next(next) {
    731   }
    732   ~prefix_node() {
    733     free(prefix);
    734   }
    735   char* prefix;
    736   const size_t prefix_len;
    737   context_node* context;
    738   struct prefix_node* next;
    739 };
    740 
    741 template <typename List, typename... Args>
    742 static inline void list_add(List** list, Args... args) {
    743   *list = new List(*list, args...);
    744 }
    745 
    746 static void list_add_after_len(prefix_node** list, const char* prefix, context_node* context) {
    747   size_t prefix_len = strlen(prefix);
    748 
    749   auto next_list = list;
    750 
    751   while (*next_list) {
    752     if ((*next_list)->prefix_len < prefix_len || (*next_list)->prefix[0] == '*') {
    753       list_add(next_list, prefix, context);
    754       return;
    755     }
    756     next_list = &(*next_list)->next;
    757   }
    758   list_add(next_list, prefix, context);
    759 }
    760 
    761 template <typename List, typename Func>
    762 static void list_foreach(List* list, Func func) {
    763   while (list) {
    764     func(list);
    765     list = list->next;
    766   }
    767 }
    768 
    769 template <typename List, typename Func>
    770 static List* list_find(List* list, Func func) {
    771   while (list) {
    772     if (func(list)) {
    773       return list;
    774     }
    775     list = list->next;
    776   }
    777   return nullptr;
    778 }
    779 
    780 template <typename List>
    781 static void list_free(List** list) {
    782   while (*list) {
    783     auto old_list = *list;
    784     *list = old_list->next;
    785     delete old_list;
    786   }
    787 }
    788 
    789 static prefix_node* prefixes = nullptr;
    790 static context_node* contexts = nullptr;
    791 
    792 /*
    793  * pthread_mutex_lock() calls into system_properties in the case of contention.
    794  * This creates a risk of dead lock if any system_properties functions
    795  * use pthread locks after system_property initialization.
    796  *
    797  * For this reason, the below three functions use a bionic Lock and static
    798  * allocation of memory for each filename.
    799  */
    800 
    801 bool context_node::open(bool access_rw, bool* fsetxattr_failed) {
    802   lock_.lock();
    803   if (pa_) {
    804     lock_.unlock();
    805     return true;
    806   }
    807 
    808   char filename[PROP_FILENAME_MAX];
    809   int len = __libc_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
    810   if (len < 0 || len > PROP_FILENAME_MAX) {
    811     lock_.unlock();
    812     return false;
    813   }
    814 
    815   if (access_rw) {
    816     pa_ = map_prop_area_rw(filename, context_, fsetxattr_failed);
    817   } else {
    818     pa_ = map_prop_area(filename);
    819   }
    820   lock_.unlock();
    821   return pa_;
    822 }
    823 
    824 bool context_node::check_access_and_open() {
    825   if (!pa_ && !no_access_) {
    826     if (!check_access() || !open(false, nullptr)) {
    827       no_access_ = true;
    828     }
    829   }
    830   return pa_;
    831 }
    832 
    833 void context_node::reset_access() {
    834   if (!check_access()) {
    835     unmap();
    836     no_access_ = true;
    837   } else {
    838     no_access_ = false;
    839   }
    840 }
    841 
    842 bool context_node::check_access() {
    843   char filename[PROP_FILENAME_MAX];
    844   int len = __libc_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
    845   if (len < 0 || len > PROP_FILENAME_MAX) {
    846     return false;
    847   }
    848 
    849   return access(filename, R_OK) == 0;
    850 }
    851 
    852 void context_node::unmap() {
    853   if (!pa_) {
    854     return;
    855   }
    856 
    857   munmap(pa_, pa_size);
    858   if (pa_ == __system_property_area__) {
    859     __system_property_area__ = nullptr;
    860   }
    861   pa_ = nullptr;
    862 }
    863 
    864 static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) {
    865   char filename[PROP_FILENAME_MAX];
    866   int len =
    867       __libc_format_buffer(filename, sizeof(filename), "%s/properties_serial", property_filename);
    868   if (len < 0 || len > PROP_FILENAME_MAX) {
    869     __system_property_area__ = nullptr;
    870     return false;
    871   }
    872 
    873   if (access_rw) {
    874     __system_property_area__ =
    875         map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
    876   } else {
    877     __system_property_area__ = map_prop_area(filename);
    878   }
    879   return __system_property_area__;
    880 }
    881 
    882 static prop_area* get_prop_area_for_name(const char* name) {
    883   auto entry = list_find(prefixes, [name](prefix_node* l) {
    884     return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
    885   });
    886   if (!entry) {
    887     return nullptr;
    888   }
    889 
    890   auto cnode = entry->context;
    891   if (!cnode->pa()) {
    892     /*
    893      * We explicitly do not check no_access_ in this case because unlike the
    894      * case of foreach(), we want to generate an selinux audit for each
    895      * non-permitted property access in this function.
    896      */
    897     cnode->open(false, nullptr);
    898   }
    899   return cnode->pa();
    900 }
    901 
    902 /*
    903  * The below two functions are duplicated from label_support.c in libselinux.
    904  * TODO: Find a location suitable for these functions such that both libc and
    905  * libselinux can share a common source file.
    906  */
    907 
    908 /*
    909  * The read_spec_entries and read_spec_entry functions may be used to
    910  * replace sscanf to read entries from spec files. The file and
    911  * property services now use these.
    912  */
    913 
    914 /* Read an entry from a spec file (e.g. file_contexts) */
    915 static inline int read_spec_entry(char** entry, char** ptr, int* len) {
    916   *entry = nullptr;
    917   char* tmp_buf = nullptr;
    918 
    919   while (isspace(**ptr) && **ptr != '\0') (*ptr)++;
    920 
    921   tmp_buf = *ptr;
    922   *len = 0;
    923 
    924   while (!isspace(**ptr) && **ptr != '\0') {
    925     (*ptr)++;
    926     (*len)++;
    927   }
    928 
    929   if (*len) {
    930     *entry = strndup(tmp_buf, *len);
    931     if (!*entry) return -1;
    932   }
    933 
    934   return 0;
    935 }
    936 
    937 /*
    938  * line_buf - Buffer containing the spec entries .
    939  * num_args - The number of spec parameter entries to process.
    940  * ...      - A 'char **spec_entry' for each parameter.
    941  * returns  - The number of items processed.
    942  *
    943  * This function calls read_spec_entry() to do the actual string processing.
    944  */
    945 static int read_spec_entries(char* line_buf, int num_args, ...) {
    946   char **spec_entry, *buf_p;
    947   int len, rc, items, entry_len = 0;
    948   va_list ap;
    949 
    950   len = strlen(line_buf);
    951   if (line_buf[len - 1] == '\n')
    952     line_buf[len - 1] = '\0';
    953   else
    954     /* Handle case if line not \n terminated by bumping
    955      * the len for the check below (as the line is NUL
    956      * terminated by getline(3)) */
    957     len++;
    958 
    959   buf_p = line_buf;
    960   while (isspace(*buf_p)) buf_p++;
    961 
    962   /* Skip comment lines and empty lines. */
    963   if (*buf_p == '#' || *buf_p == '\0') return 0;
    964 
    965   /* Process the spec file entries */
    966   va_start(ap, num_args);
    967 
    968   items = 0;
    969   while (items < num_args) {
    970     spec_entry = va_arg(ap, char**);
    971 
    972     if (len - 1 == buf_p - line_buf) {
    973       va_end(ap);
    974       return items;
    975     }
    976 
    977     rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
    978     if (rc < 0) {
    979       va_end(ap);
    980       return rc;
    981     }
    982     if (entry_len) items++;
    983   }
    984   va_end(ap);
    985   return items;
    986 }
    987 
    988 static bool initialize_properties_from_file(const char* filename) {
    989   FILE* file = fopen(filename, "re");
    990   if (!file) {
    991     return false;
    992   }
    993 
    994   char* buffer = nullptr;
    995   size_t line_len;
    996   char* prop_prefix = nullptr;
    997   char* context = nullptr;
    998 
    999   while (getline(&buffer, &line_len, file) > 0) {
   1000     int items = read_spec_entries(buffer, 2, &prop_prefix, &context);
   1001     if (items <= 0) {
   1002       continue;
   1003     }
   1004     if (items == 1) {
   1005       free(prop_prefix);
   1006       continue;
   1007     }
   1008     /*
   1009      * init uses ctl.* properties as an IPC mechanism and does not write them
   1010      * to a property file, therefore we do not need to create property files
   1011      * to store them.
   1012      */
   1013     if (!strncmp(prop_prefix, "ctl.", 4)) {
   1014       free(prop_prefix);
   1015       free(context);
   1016       continue;
   1017     }
   1018 
   1019     auto old_context =
   1020         list_find(contexts, [context](context_node* l) { return !strcmp(l->context(), context); });
   1021     if (old_context) {
   1022       list_add_after_len(&prefixes, prop_prefix, old_context);
   1023     } else {
   1024       list_add(&contexts, context, nullptr);
   1025       list_add_after_len(&prefixes, prop_prefix, contexts);
   1026     }
   1027     free(prop_prefix);
   1028     free(context);
   1029   }
   1030 
   1031   free(buffer);
   1032   fclose(file);
   1033 
   1034   return true;
   1035 }
   1036 
   1037 static bool initialize_properties() {
   1038   // If we do find /property_contexts, then this is being
   1039   // run as part of the OTA updater on older release that had
   1040   // /property_contexts - b/34370523
   1041   if (initialize_properties_from_file("/property_contexts")) {
   1042     return true;
   1043   }
   1044 
   1045   // Use property_contexts from /system & /vendor, fall back to those from /
   1046   if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
   1047     if (!initialize_properties_from_file("/system/etc/selinux/plat_property_contexts")) {
   1048       return false;
   1049     }
   1050     // Don't check for failure here, so we always have a sane list of properties.
   1051     // E.g. In case of recovery, the vendor partition will not have mounted and we
   1052     // still need the system / platform properties to function.
   1053     initialize_properties_from_file("/vendor/etc/selinux/nonplat_property_contexts");
   1054   } else {
   1055     if (!initialize_properties_from_file("/plat_property_contexts")) {
   1056       return false;
   1057     }
   1058     initialize_properties_from_file("/nonplat_property_contexts");
   1059   }
   1060 
   1061   return true;
   1062 }
   1063 
   1064 static bool is_dir(const char* pathname) {
   1065   struct stat info;
   1066   if (stat(pathname, &info) == -1) {
   1067     return false;
   1068   }
   1069   return S_ISDIR(info.st_mode);
   1070 }
   1071 
   1072 static void free_and_unmap_contexts() {
   1073   list_free(&prefixes);
   1074   list_free(&contexts);
   1075   if (__system_property_area__) {
   1076     munmap(__system_property_area__, pa_size);
   1077     __system_property_area__ = nullptr;
   1078   }
   1079 }
   1080 
   1081 int __system_properties_init() {
   1082   // This is called from __libc_init_common, and should leave errno at 0 (http://b/37248982).
   1083   ErrnoRestorer errno_restorer;
   1084 
   1085   if (initialized) {
   1086     list_foreach(contexts, [](context_node* l) { l->reset_access(); });
   1087     return 0;
   1088   }
   1089   if (is_dir(property_filename)) {
   1090     if (!initialize_properties()) {
   1091       return -1;
   1092     }
   1093     if (!map_system_property_area(false, nullptr)) {
   1094       free_and_unmap_contexts();
   1095       return -1;
   1096     }
   1097   } else {
   1098     __system_property_area__ = map_prop_area(property_filename);
   1099     if (!__system_property_area__) {
   1100       return -1;
   1101     }
   1102     list_add(&contexts, "legacy_system_prop_area", __system_property_area__);
   1103     list_add_after_len(&prefixes, "*", contexts);
   1104   }
   1105   initialized = true;
   1106   return 0;
   1107 }
   1108 
   1109 int __system_property_set_filename(const char* filename) {
   1110   size_t len = strlen(filename);
   1111   if (len >= sizeof(property_filename)) return -1;
   1112 
   1113   strcpy(property_filename, filename);
   1114   return 0;
   1115 }
   1116 
   1117 int __system_property_area_init() {
   1118   free_and_unmap_contexts();
   1119   mkdir(property_filename, S_IRWXU | S_IXGRP | S_IXOTH);
   1120   if (!initialize_properties()) {
   1121     return -1;
   1122   }
   1123   bool open_failed = false;
   1124   bool fsetxattr_failed = false;
   1125   list_foreach(contexts, [&fsetxattr_failed, &open_failed](context_node* l) {
   1126     if (!l->open(true, &fsetxattr_failed)) {
   1127       open_failed = true;
   1128     }
   1129   });
   1130   if (open_failed || !map_system_property_area(true, &fsetxattr_failed)) {
   1131     free_and_unmap_contexts();
   1132     return -1;
   1133   }
   1134   initialized = true;
   1135   return fsetxattr_failed ? -2 : 0;
   1136 }
   1137 
   1138 uint32_t __system_property_area_serial() {
   1139   prop_area* pa = __system_property_area__;
   1140   if (!pa) {
   1141     return -1;
   1142   }
   1143   // Make sure this read fulfilled before __system_property_serial
   1144   return atomic_load_explicit(pa->serial(), memory_order_acquire);
   1145 }
   1146 
   1147 const prop_info* __system_property_find(const char* name) {
   1148   if (!__system_property_area__) {
   1149     return nullptr;
   1150   }
   1151 
   1152   prop_area* pa = get_prop_area_for_name(name);
   1153   if (!pa) {
   1154     __libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
   1155     return nullptr;
   1156   }
   1157 
   1158   return pa->find(name);
   1159 }
   1160 
   1161 // The C11 standard doesn't allow atomic loads from const fields,
   1162 // though C++11 does.  Fudge it until standards get straightened out.
   1163 static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
   1164   atomic_uint_least32_t* non_const_s = const_cast<atomic_uint_least32_t*>(s);
   1165   return atomic_load_explicit(non_const_s, mo);
   1166 }
   1167 
   1168 int __system_property_read(const prop_info* pi, char* name, char* value) {
   1169   while (true) {
   1170     uint32_t serial = __system_property_serial(pi);  // acquire semantics
   1171     size_t len = SERIAL_VALUE_LEN(serial);
   1172     memcpy(value, pi->value, len + 1);
   1173     // TODO: Fix the synchronization scheme here.
   1174     // There is no fully supported way to implement this kind
   1175     // of synchronization in C++11, since the memcpy races with
   1176     // updates to pi, and the data being accessed is not atomic.
   1177     // The following fence is unintuitive, but would be the
   1178     // correct one if memcpy used memory_order_relaxed atomic accesses.
   1179     // In practice it seems unlikely that the generated code would
   1180     // would be any different, so this should be OK.
   1181     atomic_thread_fence(memory_order_acquire);
   1182     if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
   1183       if (name != nullptr) {
   1184         size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX);
   1185         if (namelen >= PROP_NAME_MAX) {
   1186           __libc_format_log(ANDROID_LOG_ERROR, "libc",
   1187                             "The property name length for \"%s\" is >= %d;"
   1188                             " please use __system_property_read_callback"
   1189                             " to read this property. (the name is truncated to \"%s\")",
   1190                             pi->name, PROP_NAME_MAX - 1, name);
   1191         }
   1192       }
   1193       return len;
   1194     }
   1195   }
   1196 }
   1197 
   1198 void __system_property_read_callback(const prop_info* pi,
   1199                                      void (*callback)(void* cookie,
   1200                                                       const char* name,
   1201                                                       const char* value,
   1202                                                       uint32_t serial),
   1203                                      void* cookie) {
   1204   while (true) {
   1205     uint32_t serial = __system_property_serial(pi);  // acquire semantics
   1206     size_t len = SERIAL_VALUE_LEN(serial);
   1207     char value_buf[len + 1];
   1208 
   1209     memcpy(value_buf, pi->value, len);
   1210     value_buf[len] = '\0';
   1211 
   1212     // TODO: see todo in __system_property_read function
   1213     atomic_thread_fence(memory_order_acquire);
   1214     if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
   1215       callback(cookie, pi->name, value_buf, serial);
   1216       return;
   1217     }
   1218   }
   1219 }
   1220 
   1221 int __system_property_get(const char* name, char* value) {
   1222   const prop_info* pi = __system_property_find(name);
   1223 
   1224   if (pi != 0) {
   1225     return __system_property_read(pi, nullptr, value);
   1226   } else {
   1227     value[0] = 0;
   1228     return 0;
   1229   }
   1230 }
   1231 
   1232 static constexpr uint32_t kProtocolVersion1 = 1;
   1233 static constexpr uint32_t kProtocolVersion2 = 2;  // current
   1234 
   1235 static atomic_uint_least32_t g_propservice_protocol_version = 0;
   1236 
   1237 static void detect_protocol_version() {
   1238   char value[PROP_VALUE_MAX];
   1239   if (__system_property_get(kServiceVersionPropertyName, value) == 0) {
   1240     g_propservice_protocol_version = kProtocolVersion1;
   1241     __libc_format_log(ANDROID_LOG_WARN, "libc",
   1242                       "Using old property service protocol (\"%s\" is not set)",
   1243                       kServiceVersionPropertyName);
   1244   } else {
   1245     uint32_t version = static_cast<uint32_t>(atoll(value));
   1246     if (version >= kProtocolVersion2) {
   1247       g_propservice_protocol_version = kProtocolVersion2;
   1248     } else {
   1249       __libc_format_log(ANDROID_LOG_WARN, "libc",
   1250                         "Using old property service protocol (\"%s\"=\"%s\")",
   1251                         kServiceVersionPropertyName, value);
   1252       g_propservice_protocol_version = kProtocolVersion1;
   1253     }
   1254   }
   1255 }
   1256 
   1257 int __system_property_set(const char* key, const char* value) {
   1258   if (key == nullptr) return -1;
   1259   if (value == nullptr) value = "";
   1260   if (strlen(value) >= PROP_VALUE_MAX) return -1;
   1261 
   1262   if (g_propservice_protocol_version == 0) {
   1263     detect_protocol_version();
   1264   }
   1265 
   1266   if (g_propservice_protocol_version == kProtocolVersion1) {
   1267     // Old protocol does not support long names
   1268     if (strlen(key) >= PROP_NAME_MAX) return -1;
   1269 
   1270     prop_msg msg;
   1271     memset(&msg, 0, sizeof msg);
   1272     msg.cmd = PROP_MSG_SETPROP;
   1273     strlcpy(msg.name, key, sizeof msg.name);
   1274     strlcpy(msg.value, value, sizeof msg.value);
   1275 
   1276     return send_prop_msg(&msg);
   1277   } else {
   1278     // Use proper protocol
   1279     PropertyServiceConnection connection;
   1280     if (!connection.IsValid()) {
   1281       errno = connection.GetLastError();
   1282       __libc_format_log(ANDROID_LOG_WARN,
   1283                         "libc",
   1284                         "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)",
   1285                         key,
   1286                         value,
   1287                         errno,
   1288                         strerror(errno));
   1289       return -1;
   1290     }
   1291 
   1292     SocketWriter writer(&connection);
   1293     if (!writer.WriteUint32(PROP_MSG_SETPROP2).WriteString(key).WriteString(value).Send()) {
   1294       errno = connection.GetLastError();
   1295       __libc_format_log(ANDROID_LOG_WARN,
   1296                         "libc",
   1297                         "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
   1298                         key,
   1299                         value,
   1300                         errno,
   1301                         strerror(errno));
   1302       return -1;
   1303     }
   1304 
   1305     int result = -1;
   1306     if (!connection.RecvInt32(&result)) {
   1307       errno = connection.GetLastError();
   1308       __libc_format_log(ANDROID_LOG_WARN,
   1309                         "libc",
   1310                         "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
   1311                         key,
   1312                         value,
   1313                         errno,
   1314                         strerror(errno));
   1315       return -1;
   1316     }
   1317 
   1318     if (result != PROP_SUCCESS) {
   1319       __libc_format_log(ANDROID_LOG_WARN,
   1320                         "libc",
   1321                         "Unable to set property \"%s\" to \"%s\": error code: 0x%x",
   1322                         key,
   1323                         value,
   1324                         result);
   1325       return -1;
   1326     }
   1327 
   1328     return 0;
   1329   }
   1330 }
   1331 
   1332 int __system_property_update(prop_info* pi, const char* value, unsigned int len) {
   1333   if (len >= PROP_VALUE_MAX) {
   1334     return -1;
   1335   }
   1336 
   1337   prop_area* pa = __system_property_area__;
   1338 
   1339   if (!pa) {
   1340     return -1;
   1341   }
   1342 
   1343   uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
   1344   serial |= 1;
   1345   atomic_store_explicit(&pi->serial, serial, memory_order_relaxed);
   1346   // The memcpy call here also races.  Again pretend it
   1347   // used memory_order_relaxed atomics, and use the analogous
   1348   // counterintuitive fence.
   1349   atomic_thread_fence(memory_order_release);
   1350   strlcpy(pi->value, value, len + 1);
   1351 
   1352   atomic_store_explicit(&pi->serial, (len << 24) | ((serial + 1) & 0xffffff), memory_order_release);
   1353   __futex_wake(&pi->serial, INT32_MAX);
   1354 
   1355   atomic_store_explicit(pa->serial(), atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
   1356                         memory_order_release);
   1357   __futex_wake(pa->serial(), INT32_MAX);
   1358 
   1359   return 0;
   1360 }
   1361 
   1362 int __system_property_add(const char* name, unsigned int namelen, const char* value,
   1363                           unsigned int valuelen) {
   1364   if (valuelen >= PROP_VALUE_MAX) {
   1365     return -1;
   1366   }
   1367 
   1368   if (namelen < 1) {
   1369     return -1;
   1370   }
   1371 
   1372   if (!__system_property_area__) {
   1373     return -1;
   1374   }
   1375 
   1376   prop_area* pa = get_prop_area_for_name(name);
   1377 
   1378   if (!pa) {
   1379     __libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
   1380     return -1;
   1381   }
   1382 
   1383   bool ret = pa->add(name, namelen, value, valuelen);
   1384   if (!ret) {
   1385     return -1;
   1386   }
   1387 
   1388   // There is only a single mutator, but we want to make sure that
   1389   // updates are visible to a reader waiting for the update.
   1390   atomic_store_explicit(
   1391       __system_property_area__->serial(),
   1392       atomic_load_explicit(__system_property_area__->serial(), memory_order_relaxed) + 1,
   1393       memory_order_release);
   1394   __futex_wake(__system_property_area__->serial(), INT32_MAX);
   1395   return 0;
   1396 }
   1397 
   1398 // Wait for non-locked serial, and retrieve it with acquire semantics.
   1399 uint32_t __system_property_serial(const prop_info* pi) {
   1400   uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire);
   1401   while (SERIAL_DIRTY(serial)) {
   1402     __futex_wait(const_cast<_Atomic(uint_least32_t)*>(&pi->serial), serial, nullptr);
   1403     serial = load_const_atomic(&pi->serial, memory_order_acquire);
   1404   }
   1405   return serial;
   1406 }
   1407 
   1408 uint32_t __system_property_wait_any(uint32_t old_serial) {
   1409   uint32_t new_serial;
   1410   __system_property_wait(nullptr, old_serial, &new_serial, nullptr);
   1411   return new_serial;
   1412 }
   1413 
   1414 bool __system_property_wait(const prop_info* pi,
   1415                             uint32_t old_serial,
   1416                             uint32_t* new_serial_ptr,
   1417                             const timespec* relative_timeout) {
   1418   // Are we waiting on the global serial or a specific serial?
   1419   atomic_uint_least32_t* serial_ptr;
   1420   if (pi == nullptr) {
   1421     if (__system_property_area__ == nullptr) return -1;
   1422     serial_ptr = __system_property_area__->serial();
   1423   } else {
   1424     serial_ptr = const_cast<atomic_uint_least32_t*>(&pi->serial);
   1425   }
   1426 
   1427   uint32_t new_serial;
   1428   do {
   1429     int rc;
   1430     if ((rc = __futex_wait(serial_ptr, old_serial, relative_timeout)) != 0 && rc == -ETIMEDOUT) {
   1431       return false;
   1432     }
   1433     new_serial = load_const_atomic(serial_ptr, memory_order_acquire);
   1434   } while (new_serial == old_serial);
   1435 
   1436   *new_serial_ptr = new_serial;
   1437   return true;
   1438 }
   1439 
   1440 const prop_info* __system_property_find_nth(unsigned n) {
   1441   struct find_nth {
   1442     const uint32_t sought;
   1443     uint32_t current;
   1444     const prop_info* result;
   1445 
   1446     explicit find_nth(uint32_t n) : sought(n), current(0), result(nullptr) {}
   1447     static void fn(const prop_info* pi, void* ptr) {
   1448       find_nth* self = reinterpret_cast<find_nth*>(ptr);
   1449       if (self->current++ == self->sought) self->result = pi;
   1450     }
   1451   } state(n);
   1452   __system_property_foreach(find_nth::fn, &state);
   1453   return state.result;
   1454 }
   1455 
   1456 int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
   1457   if (!__system_property_area__) {
   1458     return -1;
   1459   }
   1460 
   1461   list_foreach(contexts, [propfn, cookie](context_node* l) {
   1462     if (l->check_access_and_open()) {
   1463       l->pa()->foreach(propfn, cookie);
   1464     }
   1465   });
   1466   return 0;
   1467 }
   1468