diff --git a/native/src/base/Android.mk b/native/src/base/Android.mk index 4c1852ee4..5024157f5 100644 --- a/native/src/base/Android.mk +++ b/native/src/base/Android.mk @@ -18,7 +18,6 @@ LOCAL_SRC_FILES := \ files.cpp \ misc.cpp \ logging.cpp \ - stream.cpp \ base-rs.cpp \ ../external/cxx-rs/src/cxx.cc include $(BUILD_STATIC_LIBRARY) diff --git a/native/src/base/include/stream.hpp b/native/src/base/include/stream.hpp deleted file mode 100644 index adad83675..000000000 --- a/native/src/base/include/stream.hpp +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "../files.hpp" - -#define ENABLE_IOV 0 - -struct out_stream { - virtual bool write(const void *buf, size_t len) = 0; -#if ENABLE_IOV - virtual ssize_t writev(const iovec *iov, int iovcnt); -#endif - virtual ~out_stream() = default; -}; - -using out_strm_ptr = std::unique_ptr; - -// Delegates all operations to base stream -class filter_out_stream : public out_stream { -public: - filter_out_stream(out_strm_ptr &&base) : base(std::move(base)) {} - bool write(const void *buf, size_t len) override; -protected: - out_strm_ptr base; -}; - -// Buffered output stream, writing in chunks -class chunk_out_stream : public filter_out_stream { -public: - chunk_out_stream(out_strm_ptr &&base, size_t buf_sz, size_t chunk_sz) - : filter_out_stream(std::move(base)), chunk_sz(chunk_sz), data(buf_sz) {} - - chunk_out_stream(out_strm_ptr &&base, size_t buf_sz = 4096) - : chunk_out_stream(std::move(base), buf_sz, buf_sz) {} - - bool write(const void *buf, size_t len) final; - -protected: - // Classes inheriting this class has to call finalize() in its destructor - void finalize(); - virtual bool write_chunk(const void *buf, size_t len, bool final); - - size_t chunk_sz; - -private: - size_t buf_off = 0; - heap_data data; -}; - -struct in_stream { - virtual ssize_t read(void *buf, size_t len) = 0; - ssize_t readFully(void *buf, size_t len); -#if ENABLE_IOV - virtual ssize_t readv(const iovec *iov, int iovcnt); -#endif - virtual ~in_stream() = default; -}; - -// A stream is something that is writable and readable -struct stream : public out_stream, public in_stream {}; - -using stream_ptr = std::unique_ptr; - -// Byte stream that dynamically allocates memory -class byte_stream : public stream { -public: - byte_stream(heap_data &data) : _data(data) {} - - ssize_t read(void *buf, size_t len) override; - bool write(const void *buf, size_t len) override; - -private: - heap_data &_data; - size_t _pos = 0; - size_t _cap = 0; - - void resize(size_t new_sz, bool zero = false); -}; - -class rust_vec_stream : public stream { -public: - rust_vec_stream(rust::Vec &data) : _data(data) {} - - ssize_t read(void *buf, size_t len) override; - bool write(const void *buf, size_t len) override; - -private: - rust::Vec &_data; - size_t _pos = 0; - - void ensure_size(size_t sz, bool zero = false); -}; - -class file_stream : public stream { -public: - bool write(const void *buf, size_t len) final; -protected: - virtual ssize_t do_write(const void *buf, size_t len) = 0; -}; - -// File stream but does not close the file descriptor at any time -class fd_stream : public file_stream { -public: - fd_stream(int fd) : fd(fd) {} - ssize_t read(void *buf, size_t len) override; -#if ENABLE_IOV - ssize_t readv(const iovec *iov, int iovcnt) override; - ssize_t writev(const iovec *iov, int iovcnt) override; -#endif -protected: - ssize_t do_write(const void *buf, size_t len) override; -private: - int fd; -}; - -/* **************************************** - * Bridge between stream class and C stdio - * ****************************************/ - -// stream_ptr -> sFILE -sFILE make_stream_fp(stream_ptr &&strm); - -template -sFILE make_stream_fp(Args &&... args) { - return make_stream_fp(stream_ptr(new T(std::forward(args)...))); -} diff --git a/native/src/base/lib.rs b/native/src/base/lib.rs index 33f237ac6..65e5ed4b9 100644 --- a/native/src/base/lib.rs +++ b/native/src/base/lib.rs @@ -58,7 +58,6 @@ pub mod ffi { fn set_log_level_state_cxx(level: LogLevelCxx, enabled: bool); fn exit_on_error(b: bool); fn cmdline_logging(); - fn resize_vec(vec: &mut Vec, size: usize); } #[namespace = "rust"] @@ -80,12 +79,3 @@ fn set_log_level_state_cxx(level: ffi::LogLevelCxx, enabled: bool) { set_log_level_state(level, enabled) } } - -fn resize_vec(vec: &mut Vec, size: usize) { - if size > vec.len() { - vec.reserve(size - vec.len()); - } - unsafe { - vec.set_len(size); - } -} diff --git a/native/src/base/misc.hpp b/native/src/base/misc.hpp index b42780a47..affeb5226 100644 --- a/native/src/base/misc.hpp +++ b/native/src/base/misc.hpp @@ -147,17 +147,12 @@ struct byte_data : public byte_view { rust::Vec patch(byte_view from, byte_view to); }; -class byte_stream; - struct heap_data : public byte_data { ALLOW_MOVE_ONLY(heap_data) heap_data() = default; explicit heap_data(size_t sz) : byte_data(calloc(sz, 1), sz) {} ~heap_data() { free(_buf); } - - // byte_stream needs to reallocate the internal buffer - friend byte_stream; }; struct owned_fd { diff --git a/native/src/base/stream.cpp b/native/src/base/stream.cpp deleted file mode 100644 index c276ff6ca..000000000 --- a/native/src/base/stream.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include -#include - -#include -#include - -using namespace std; - -static int strm_read(void *v, char *buf, int len) { - auto strm = static_cast(v); - return strm->read(buf, len); -} - -static int strm_write(void *v, const char *buf, int len) { - auto strm = static_cast(v); - if (!strm->write(buf, len)) - return -1; - return len; -} - -static int strm_close(void *v) { - auto strm = static_cast(v); - delete strm; - return 0; -} - -sFILE make_stream_fp(stream_ptr &&strm) { - auto fp = make_file(funopen(strm.release(), strm_read, strm_write, nullptr, strm_close)); - setbuf(fp.get(), nullptr); - return fp; -} - -ssize_t in_stream::readFully(void *buf, size_t len) { - size_t read_sz = 0; - ssize_t ret; - do { - ret = read((byte *) buf + read_sz, len - read_sz); - if (ret < 0) { - if (errno == EINTR) - continue; - return ret; - } - read_sz += ret; - } while (read_sz != len && ret != 0); - return read_sz; -} - -bool filter_out_stream::write(const void *buf, size_t len) { - return base->write(buf, len); -} - -bool chunk_out_stream::write(const void *_in, size_t len) { - auto in = static_cast(_in); - while (len) { - if (buf_off + len >= chunk_sz) { - // Enough input for a chunk - const uint8_t *src; - if (buf_off) { - src = data.buf(); - auto copy = chunk_sz - buf_off; - memcpy(data.buf() + buf_off, in, copy); - in += copy; - len -= copy; - buf_off = 0; - } else { - src = in; - in += chunk_sz; - len -= chunk_sz; - } - if (!write_chunk(src, chunk_sz, false)) - return false; - } else { - // Buffer internally - memcpy(data.buf() + buf_off, in, len); - buf_off += len; - break; - } - } - return true; -} - -bool chunk_out_stream::write_chunk(const void *buf, size_t len, bool) { - return base->write(buf, len); -} - -void chunk_out_stream::finalize() { - if (buf_off) { - if (!write_chunk(data.buf(), buf_off, true)) { - LOGE("Error in finalize, file truncated\n"); - } - buf_off = 0; - } -} - -ssize_t byte_stream::read(void *buf, size_t len) { - len = std::min((size_t) len, _data._sz- _pos); - memcpy(buf, _data.buf() + _pos, len); - _pos += len; - return len; -} - -bool byte_stream::write(const void *buf, size_t len) { - resize(_pos + len); - memcpy(_data.buf() + _pos, buf, len); - _pos += len; - _data._sz= std::max(_data.sz(), _pos); - return true; -} - -void byte_stream::resize(size_t new_sz, bool zero) { - bool resize = false; - size_t old_cap = _cap; - while (new_sz > _cap) { - _cap = _cap ? (_cap << 1) - (_cap >> 1) : 1 << 12; - resize = true; - } - if (resize) { - _data._buf = static_cast(::realloc(_data._buf, _cap)); - if (zero) - memset(_data.buf() + old_cap, 0, _cap - old_cap); - } -} - -ssize_t rust_vec_stream::read(void *buf, size_t len) { - len = std::min(len, _data.size() - _pos); - memcpy(buf, _data.data() + _pos, len); - _pos += len; - return len; -} - -bool rust_vec_stream::write(const void *buf, size_t len) { - ensure_size(_pos + len); - memcpy(_data.data() + _pos, buf, len); - _pos += len; - return true; -} - -void rust_vec_stream::ensure_size(size_t sz, bool zero) { - size_t old_sz = _data.size(); - if (sz > old_sz) { - resize_vec(_data, sz); - if (zero) - memset(_data.data() + old_sz, 0, sz - old_sz); - } -} - -ssize_t fd_stream::read(void *buf, size_t len) { - return ::read(fd, buf, len); -} - -ssize_t fd_stream::do_write(const void *buf, size_t len) { - return ::write(fd, buf, len); -} - -bool file_stream::write(const void *buf, size_t len) { - size_t write_sz = 0; - ssize_t ret; - do { - ret = do_write((byte *) buf + write_sz, len - write_sz); - if (ret < 0) { - if (errno == EINTR) - continue; - return false; - } - write_sz += ret; - } while (write_sz != len && ret != 0); - return true; -} - -#if ENABLE_IOV - -ssize_t in_stream::readv(const iovec *iov, int iovcnt) { - size_t read_sz = 0; - for (int i = 0; i < iovcnt; ++i) { - auto ret = readFully(iov[i].iov_base, iov[i].iov_len); - if (ret < 0) - return ret; - read_sz += ret; - } - return read_sz; -} - -ssize_t out_stream::writev(const iovec *iov, int iovcnt) { - size_t write_sz = 0; - for (int i = 0; i < iovcnt; ++i) { - if (!write(iov[i].iov_base, iov[i].iov_len)) - return write_sz; - write_sz += iov[i].iov_len; - } - return write_sz; -} - -ssize_t fd_stream::readv(const iovec *iov, int iovcnt) { - return ::readv(fd, iov, iovcnt); -} - -ssize_t fd_stream::writev(const iovec *iov, int iovcnt) { - return ::writev(fd, iov, iovcnt); -} - -#endif // ENABLE_IOV diff --git a/native/src/init/init.hpp b/native/src/init/init.hpp index d799722af..76f9fe7e4 100644 --- a/native/src/init/init.hpp +++ b/native/src/init/init.hpp @@ -10,7 +10,6 @@ #ifdef __cplusplus #include -#include #include #include "init-rs.hpp" diff --git a/native/src/init/rootdir.cpp b/native/src/init/rootdir.cpp index b6f1699b3..5ae3b498b 100644 --- a/native/src/init/rootdir.cpp +++ b/native/src/init/rootdir.cpp @@ -17,7 +17,7 @@ static vector rc_list; #define NEW_INITRC_DIR "/system/etc/init/hw" #define INIT_RC "init.rc" -static bool unxz(out_stream &strm, rust::Slice bytes) { +static bool unxz(int fd, rust::Slice bytes) { uint8_t out[8192]; xz_crc32_init(); size_t size = bytes.size(); @@ -36,7 +36,7 @@ static bool unxz(out_stream &strm, rust::Slice bytes) { ret = xz_dec_run(dec, &b); if (ret != XZ_OK && ret != XZ_STREAM_END) return false; - strm.write(out, b.out_pos); + write(fd, out, b.out_pos); b.out_pos = 0; } while (b.in_pos != size); return true; @@ -241,24 +241,21 @@ static void extract_files(bool sbin) { mmap_data magisk(magisk_xz); unlink(magisk_xz); int fd = xopen("magisk", O_WRONLY | O_CREAT, 0755); - fd_stream ch(fd); - unxz(ch, magisk); + unxz(fd, magisk); close(fd); } if (access(stub_xz, F_OK) == 0) { mmap_data stub(stub_xz); unlink(stub_xz); int fd = xopen("stub.apk", O_WRONLY | O_CREAT, 0); - fd_stream ch(fd); - unxz(ch, stub); + unxz(fd, stub); close(fd); } if (access(init_ld_xz, F_OK) == 0) { mmap_data init_ld(init_ld_xz); unlink(init_ld_xz); int fd = xopen("init-ld", O_WRONLY | O_CREAT, 0); - fd_stream ch(fd); - unxz(ch, init_ld); + unxz(fd, init_ld); close(fd); } } @@ -407,8 +404,7 @@ int magisk_proxy_main(int, char *argv[]) { static void unxz_init(const char *init_xz, const char *init) { LOGD("unxz %s -> %s\n", init_xz, init); int fd = xopen(init, O_WRONLY | O_CREAT, 0777); - fd_stream ch(fd); - unxz(ch, mmap_data{init_xz}); + unxz(fd, mmap_data{init_xz}); close(fd); clone_attr(init_xz, init); unlink(init_xz); diff --git a/native/src/sepolicy/policydb.cpp b/native/src/sepolicy/policydb.cpp index 0c2e32507..24ef3fab2 100644 --- a/native/src/sepolicy/policydb.cpp +++ b/native/src/sepolicy/policydb.cpp @@ -8,8 +8,8 @@ #include #include -#include +using namespace std; #define SHALEN 64 static bool cmp_sha256(const char *a, const char *b) { @@ -230,20 +230,29 @@ sepol_impl::~sepol_impl() { free(db); } +static int vec_write(void *v, const char *buf, int len) { + auto vec = static_cast *>(v); + vec->insert(vec->end(), buf, buf + len); + return len; +} + bool SePolicy::to_file(::rust::Utf8CStr file) const noexcept { // No partial writes are allowed to /sys/fs/selinux/load, thus the reason why we // first dump everything into memory, then directly call write system call - heap_data data; - auto fp = make_stream_fp(data); + vector out; + FILE *fp = funopen(&out, nullptr, vec_write, nullptr, nullptr); + // Since we're directly writing to memory, disable buffering + setbuf(fp, nullptr); policy_file_t pf; policy_file_init(&pf); pf.type = PF_USE_STDIO; - pf.fp = fp.get(); + pf.fp = fp; if (policydb_write(impl->db, &pf)) { LOGE("Fail to create policy image\n"); return false; } + fclose(fp); int fd = xopen(file.data(), O_WRONLY | O_CREAT | O_CLOEXEC, 0644); if (fd < 0) @@ -251,7 +260,7 @@ bool SePolicy::to_file(::rust::Utf8CStr file) const noexcept { if (struct stat st{}; xfstat(fd, &st) == 0 && st.st_size > 0) { ftruncate(fd, 0); } - xwrite(fd, data.buf(), data.sz()); + xwrite(fd, out.data(), out.size()); close(fd); return true;