From 45a1be038c6e4c72f8ee2d7879bf719c7765b514 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 17 May 2023 00:44:08 -0700 Subject: [PATCH] Support mapping prop_area as rw --- context_node.cpp | 2 +- contexts_serialized.cpp | 2 +- contexts_split.cpp | 2 +- include/system_properties/contexts.h | 1 + .../system_properties/contexts_pre_split.h | 2 +- include/system_properties/prop_area.h | 4 ++-- prop_area.cpp | 22 ++++++++++++++----- system_properties.cpp | 8 +++++++ 8 files changed, 31 insertions(+), 12 deletions(-) diff --git a/context_node.cpp b/context_node.cpp index 572bf97..18056e9 100644 --- a/context_node.cpp +++ b/context_node.cpp @@ -53,7 +53,7 @@ bool ContextNode::Open(bool access_rw, bool* fsetxattr_failed) { if (access_rw) { pa_ = prop_area::map_prop_area_rw(filename.c_str(), context_, fsetxattr_failed); } else { - pa_ = prop_area::map_prop_area(filename.c_str()); + pa_ = prop_area::map_prop_area(filename.c_str(), nullptr); } lock_.unlock(); return pa_; diff --git a/contexts_serialized.cpp b/contexts_serialized.cpp index 6aabb7f..254a9cc 100644 --- a/contexts_serialized.cpp +++ b/contexts_serialized.cpp @@ -70,7 +70,7 @@ bool ContextsSerialized::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_f serial_prop_area_ = prop_area::map_prop_area_rw( serial_filename_.c_str(), "u:object_r:properties_serial:s0", fsetxattr_failed); } else { - serial_prop_area_ = prop_area::map_prop_area(serial_filename_.c_str()); + serial_prop_area_ = prop_area::map_prop_area(serial_filename_.c_str(), &rw_); } return serial_prop_area_; } diff --git a/contexts_split.cpp b/contexts_split.cpp index 8317484..dca5132 100644 --- a/contexts_split.cpp +++ b/contexts_split.cpp @@ -197,7 +197,7 @@ bool ContextsSplit::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed serial_prop_area_ = prop_area::map_prop_area_rw( filename.c_str(), "u:object_r:properties_serial:s0", fsetxattr_failed); } else { - serial_prop_area_ = prop_area::map_prop_area(filename.c_str()); + serial_prop_area_ = prop_area::map_prop_area(filename.c_str(), &rw_); } return serial_prop_area_; } diff --git a/include/system_properties/contexts.h b/include/system_properties/contexts.h index df8c5a2..a59c063 100644 --- a/include/system_properties/contexts.h +++ b/include/system_properties/contexts.h @@ -43,4 +43,5 @@ class Contexts { virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) = 0; virtual void ResetAccess() = 0; virtual void FreeAndUnmap() = 0; + bool rw_ = false; }; diff --git a/include/system_properties/contexts_pre_split.h b/include/system_properties/contexts_pre_split.h index a6cd039..52f08f9 100644 --- a/include/system_properties/contexts_pre_split.h +++ b/include/system_properties/contexts_pre_split.h @@ -39,7 +39,7 @@ class ContextsPreSplit : public Contexts { // We'll never initialize this legacy option as writable, so don't even check the arg. virtual bool Initialize(bool, const char* filename, bool*, bool) override { - pre_split_prop_area_ = prop_area::map_prop_area(filename); + pre_split_prop_area_ = prop_area::map_prop_area(filename, &rw_); return pre_split_prop_area_ != nullptr; } diff --git a/include/system_properties/prop_area.h b/include/system_properties/prop_area.h index 187ff75..f466b58 100644 --- a/include/system_properties/prop_area.h +++ b/include/system_properties/prop_area.h @@ -93,7 +93,7 @@ class prop_area { public: static prop_area* map_prop_area_rw(const char* filename, const char* context, bool* fsetxattr_failed); - static prop_area* map_prop_area(const char* filename); + static prop_area* map_prop_area(const char* filename, bool *is_rw); static void unmap_prop_area(prop_area** pa) { if (*pa) { munmap(*pa, pa_size_); @@ -139,7 +139,7 @@ class prop_area { char* dirty_backup_area() { return data_ + sizeof(prop_trie_node); } private: - static prop_area* map_fd_ro(const int fd); + static prop_area* map_fd_ro(const int fd, bool rw); void* allocate_obj(const size_t size, uint_least32_t* const off); prop_trie_node* new_prop_trie_node(const char* name, uint32_t namelen, uint_least32_t* const off); diff --git a/prop_area.cpp b/prop_area.cpp index 4668eed..318e677 100644 --- a/prop_area.cpp +++ b/prop_area.cpp @@ -104,7 +104,7 @@ prop_area* prop_area::map_prop_area_rw(const char* filename, const char* context return pa; } -prop_area* prop_area::map_fd_ro(const int fd) { +prop_area* prop_area::map_fd_ro(const int fd, bool rw) { struct stat fd_stat; if (fstat(fd, &fd_stat) < 0) { return nullptr; @@ -119,7 +119,8 @@ prop_area* prop_area::map_fd_ro(const int fd) { pa_size_ = fd_stat.st_size; pa_data_size_ = pa_size_ - sizeof(prop_area); - void* const map_result = mmap(nullptr, pa_size_, PROT_READ, MAP_SHARED, fd, 0); + int prot = rw ? PROT_READ | PROT_WRITE : PROT_READ; + void* const map_result = mmap(nullptr, pa_size_, prot, MAP_SHARED, fd, 0); if (map_result == MAP_FAILED) { return nullptr; } @@ -133,13 +134,22 @@ prop_area* prop_area::map_fd_ro(const int fd) { return pa; } -prop_area* prop_area::map_prop_area(const char* filename) { - int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY); - if (fd == -1) return nullptr; +prop_area* prop_area::map_prop_area(const char* filename, bool *is_rw) { + bool rw = false; + int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDWR); + if (fd == -1) { + fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY); + if (fd == -1) { + return nullptr; + } + } else { + rw = true; + } - prop_area* map_result = map_fd_ro(fd); + prop_area* map_result = map_fd_ro(fd, rw); close(fd); + if (is_rw) *is_rw = rw; return map_result; } diff --git a/system_properties.cpp b/system_properties.cpp index 4d3f6b6..7b58852 100644 --- a/system_properties.cpp +++ b/system_properties.cpp @@ -276,6 +276,10 @@ int SystemProperties::Update(prop_info* pi, const char* value, unsigned int len) } bool have_override = appcompat_override_contexts_ != nullptr; + if (!contexts_->rw_) { + return -1; + } + prop_area* serial_pa = contexts_->GetSerialPropArea(); prop_area* override_serial_pa = have_override ? appcompat_override_contexts_->GetSerialPropArea() : nullptr; @@ -355,6 +359,10 @@ int SystemProperties::Add(const char* name, unsigned int namelen, const char* va return -1; } + if (!contexts_->rw_) { + return -1; + } + prop_area* serial_pa = contexts_->GetSerialPropArea(); if (serial_pa == nullptr) { async_safe_format_log(ANDROID_LOG_ERROR, "libc",