blob: 551abb2fab197d3815aa422f1ba8f73b01da8b21 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/hermetic-decompressor/hermetic-decompressor.h>
#include <fuchsia/ldsvc/c/fidl.h>
#include <string_view>
#include <zircon/dlfcn.h>
namespace {
// This "borrows" the ldsvc handle from libdl by stealing it and then giving it
// back. So it's not thread-safe with respect to concurrent dlopen calls.
class UseLdsvc {
public:
UseLdsvc(const UseLdsvc&) = delete;
UseLdsvc(UseLdsvc&&) = delete;
UseLdsvc() : ldsvc_(dl_set_loader_service({})) {}
~UseLdsvc() { dl_set_loader_service(ldsvc_->get()); }
zx_status_t operator()(std::string_view name, zx::vmo* vmo) {
int32_t rv;
zx_status_t status = fuchsia_ldsvc_LoaderLoadObject(
ldsvc_->get(), name.data(), name.size(),
&rv, vmo->reset_and_get_address());
return status == ZX_OK ? rv : status;
}
private:
zx::unowned_channel ldsvc_;
};
struct Decompressor {
std::string_view name;
zx::vmo* cache;
HermeticDecompressorEngineService::Magic magic;
};
zx::vmo cache_lz4f, cache_zstd;
constexpr Decompressor kDecompressors[] = {
{"hermetic/decompress-lz4f.so", &cache_lz4f,
HermeticDecompressorEngineService::kLz4fMagic},
{"hermetic/decompress-zstd.so", &cache_zstd,
HermeticDecompressorEngineService::kZstdMagic},
};
} // namespace
zx_status_t HermeticDecompressorEngineService::GetEngine(
Magic magic, zx::unowned_vmo* vmo) {
for (const auto& engine : kDecompressors) {
if (engine.magic == magic) {
if (!*engine.cache) {
// Fetch the applicable engine by name from the loader service.
zx_status_t status = UseLdsvc()(engine.name, engine.cache);
if (status != ZX_OK) {
return status;
}
}
*vmo = zx::unowned_vmo{*engine.cache};
return ZX_OK;
}
}
return ZX_ERR_NOT_FOUND;
}