1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef BERBERIS_BASE_EXEC_REGION_H_ 18 #define BERBERIS_BASE_EXEC_REGION_H_ 19 20 #include <cstddef> 21 #include <cstdint> 22 23 namespace berberis { 24 25 // ExecRegion manages a range of writable executable memory. 26 // This implementation works with 2 mappings of memfd file, 27 // one is executable and is read only another one is writable 28 // and not executable. 29 // 30 // Because both mappings are backed by memfd file msync is not 31 // needed in order to keep them up to date. It is backed by shmem 32 // and always consistent. shmem implementation of fsync is no-op: 33 // https://github.com/torvalds/linux/blob/3de0c269adc6c2fac0bb1fb11965f0de699dc32b/mm/shmem.c#L3931 34 // 35 // 36 // Move-only! 37 class ExecRegion { 38 public: 39 ExecRegion() = default; ExecRegion(uint8_t * exec,uint8_t * write,size_t size)40 explicit ExecRegion(uint8_t* exec, uint8_t* write, size_t size) 41 : exec_{exec}, write_{write}, size_{size} {} 42 43 ExecRegion(const ExecRegion& other) = delete; 44 ExecRegion& operator=(const ExecRegion& other) = delete; 45 ExecRegion(ExecRegion && other)46 ExecRegion(ExecRegion&& other) noexcept { 47 exec_ = other.exec_; 48 write_ = other.write_; 49 size_ = other.size_; 50 other.exec_ = nullptr; 51 other.write_ = nullptr; 52 other.size_ = 0; 53 } 54 55 ExecRegion& operator=(ExecRegion&& other) noexcept { 56 if (this == &other) { 57 return *this; 58 } 59 exec_ = other.exec_; 60 write_ = other.write_; 61 size_ = other.size_; 62 other.exec_ = nullptr; 63 other.write_ = nullptr; 64 other.size_ = 0; 65 return *this; 66 } 67 begin()68 [[nodiscard]] const uint8_t* begin() const { return exec_; } end()69 [[nodiscard]] const uint8_t* end() const { return exec_ + size_; } 70 71 void Write(const uint8_t* dst, const void* src, size_t size); 72 73 void Detach(); 74 void Free(); 75 76 private: 77 uint8_t* exec_ = nullptr; 78 uint8_t* write_ = nullptr; 79 size_t size_ = 0; 80 }; 81 82 } // namespace berberis 83 84 #endif // BERBERIS_BASE_EXEC_REGION_H_ 85