From 102b2e96623d858e84213a1ae176c251307286e7 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 19 Jan 2024 18:52:37 +0900 Subject: [PATCH] Mount gadget resource paths for NUIGadget After this patch is applied, the launchpad tries to mount the gadget resource package separately. And, the gadget packages will be mounted to the bin directory of the application. The 'loader-mount' process is added for mounting gadget packages. Change-Id: Id6c4e6b5a3525eb5cc8687fbb28b6292e895ff3e Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/app_executor.cc | 6 + src/launchpad-process-pool/hydra_loader_context.cc | 10 +- src/launchpad-process-pool/hydra_loader_context.hh | 3 +- src/launchpad-process-pool/loader_context.cc | 22 +- src/launchpad-process-pool/loader_context.hh | 7 +- src/launchpad-process-pool/loader_factory.cc | 19 +- src/launchpad-process-pool/loader_factory.hh | 11 +- src/launchpad-process-pool/loader_manager.cc | 22 +- src/launchpad-process-pool/loader_manager.hh | 5 + src/launchpad-process-pool/loader_mount.cc | 329 +++++++++++++++++++++ src/launchpad-process-pool/loader_mount.hh | 61 ++++ src/lib/launchpad-common/aul_keys.hh | 2 + src/lib/launchpad-glib/util.cc | 29 +- src/lib/launchpad-glib/util.hh | 1 + src/lib/launchpad/step_prepare_execution.cc | 7 + 15 files changed, 508 insertions(+), 26 deletions(-) create mode 100644 src/launchpad-process-pool/loader_mount.cc create mode 100644 src/launchpad-process-pool/loader_mount.hh diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index afb2e94..c47d3cf 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -200,6 +200,12 @@ int AppExecutor::StepEnableTrustAnchor() { } int AppExecutor::StepMountResDir() { + int ret = Util::MountGadgetDirectories(app_info_->GetBundle()); + if (ret != 0) { + _E("Failed to mount gadget resources"); + return ret; + } + return Util::MountResourceDirectories(app_info_); } diff --git a/src/launchpad-process-pool/hydra_loader_context.cc b/src/launchpad-process-pool/hydra_loader_context.cc index a2d29db..88bbf6c 100644 --- a/src/launchpad-process-pool/hydra_loader_context.cc +++ b/src/launchpad-process-pool/hydra_loader_context.cc @@ -39,12 +39,14 @@ const int kSocketMaxBufferSize = 131071; HydraLoaderContext::Builder::operator LoaderContext*() { return new HydraLoaderContext(std::move(loader_info_), loader_id_, - caller_pid_, activated_); + caller_pid_, activated_, std::move(loader_mount_)); } -HydraLoaderContext::HydraLoaderContext(std::shared_ptr loader_info, - int loader_id, pid_t caller_pid, bool activated) - : LoaderContext(std::move(loader_info), loader_id, caller_pid, activated) { +HydraLoaderContext::HydraLoaderContext( + std::shared_ptr loader_info, int loader_id, pid_t caller_pid, + bool activated, std::shared_ptr loader_mount) + : LoaderContext(std::move(loader_info), loader_id, caller_pid, activated, + std::move(loader_mount)) { Listen(); } diff --git a/src/launchpad-process-pool/hydra_loader_context.hh b/src/launchpad-process-pool/hydra_loader_context.hh index 88f2fbd..2b5945d 100644 --- a/src/launchpad-process-pool/hydra_loader_context.hh +++ b/src/launchpad-process-pool/hydra_loader_context.hh @@ -33,7 +33,8 @@ class HydraLoaderContext : public LoaderContext { }; HydraLoaderContext(std::shared_ptr loader_info, int loader_id, - pid_t caller_pid, bool activated); + pid_t caller_pid, bool activated, + std::shared_ptr loader_mount); void Listen() override; void Dispose() override; diff --git a/src/launchpad-process-pool/loader_context.cc b/src/launchpad-process-pool/loader_context.cc index 10b2b87..513dc78 100644 --- a/src/launchpad-process-pool/loader_context.cc +++ b/src/launchpad-process-pool/loader_context.cc @@ -124,20 +124,27 @@ LoaderContext::Builder& LoaderContext::Builder::SetActive() { return *this; } +LoaderContext::Builder& LoaderContext::Builder::SetLoaderMount( + std::shared_ptr loader_mount) { + loader_mount_ = std::move(loader_mount); + return *this; +} + LoaderContext::Builder::operator LoaderContext*() { return new LoaderContext(std::move(loader_info_), loader_id_, caller_pid_, - activated_); + activated_, std::move(loader_mount_)); } LoaderContext::LoaderContext(std::shared_ptr loader_info, - int loader_id, pid_t caller_pid, bool activated) + int loader_id, pid_t caller_pid, bool activated, + std::shared_ptr loader_mount) : loader_info_(std::move(loader_info)), loader_id_(loader_id), caller_pid_(caller_pid), activated_(activated), - cpu_checker_( - new CPUChecker(loader_info_->GetCpuThresholdMax(), - loader_info_->GetCpuThresholdMin())), + loader_mount_(std::move(loader_mount)), + cpu_checker_(new CPUChecker(loader_info_->GetCpuThresholdMax(), + loader_info_->GetCpuThresholdMin())), score_(kWinScore) { auto& executable_file = loader_info_->GetExe(); if (executable_file != "null") { @@ -238,6 +245,11 @@ pid_t LoaderContext::Prepare() { } pid_t LoaderContext::Deploy(const AppInfo* app_info) { + if (loader_mount_) { + if (loader_mount_->Mount(pid_, app_info) != 0) + _E("Failed to attach resources to loader process"); + } + Util::DeleteSocketPath(pid_, getuid()); tizen_base::Parcel parcel; parcel.WriteParcelable(*app_info); diff --git a/src/launchpad-process-pool/loader_context.hh b/src/launchpad-process-pool/loader_context.hh index feaf15d..814ff4b 100644 --- a/src/launchpad-process-pool/loader_context.hh +++ b/src/launchpad-process-pool/loader_context.hh @@ -32,6 +32,7 @@ #include "launchpad-process-pool/cpu_checker.hh" #include "launchpad-process-pool/loader_info.hh" #include "launchpad-process-pool/launcher_info.hh" +#include "launchpad-process-pool/loader_mount.hh" namespace launchpad { @@ -46,6 +47,7 @@ class LoaderContext : public std::enable_shared_from_this, Builder& SetLoaderId(int loader_id); Builder& SetCallerPid(pid_t caller_pid); Builder& SetActive(); + Builder& SetLoaderMount(std::shared_ptr loader_mount); virtual operator LoaderContext*(); @@ -54,6 +56,7 @@ class LoaderContext : public std::enable_shared_from_this, int loader_id_ = 0; pid_t caller_pid_ = getpid(); bool activated_ = true; + std::shared_ptr loader_mount_; }; class IEvent { @@ -65,7 +68,8 @@ class LoaderContext : public std::enable_shared_from_this, }; LoaderContext(std::shared_ptr loader_info, int loader_id, - pid_t caller_pid, bool activated); + pid_t caller_pid, bool activated, + std::shared_ptr loader_mount); virtual ~LoaderContext(); virtual void Listen(); @@ -136,6 +140,7 @@ class LoaderContext : public std::enable_shared_from_this, int loader_id_; pid_t caller_pid_; bool activated_; + std::shared_ptr loader_mount_; std::unique_ptr cpu_checker_; unsigned int score_; std::string loader_extra_; diff --git a/src/launchpad-process-pool/loader_factory.cc b/src/launchpad-process-pool/loader_factory.cc index e62b8c3..5d9b604 100644 --- a/src/launchpad-process-pool/loader_factory.cc +++ b/src/launchpad-process-pool/loader_factory.cc @@ -75,7 +75,7 @@ LoaderFactory& LoaderFactory::GetInst() { } std::shared_ptr LoaderFactory::CreateLoaderContext( - LoaderInfoPtr info) { + LoaderInfoPtr info, std::shared_ptr loader_mount) { auto app_types = GetAppTypeString(info); int loader_id = static_cast((info->GetExe() == "null") ? PadLoaderId::Direct : PadLoaderId::Static); @@ -85,12 +85,14 @@ std::shared_ptr LoaderFactory::CreateLoaderContext( context = HydraLoaderContext::Builder() .SetLoaderInfo(std::move(info)) .SetLoaderId(loader_id) - .SetActive(); + .SetActive() + .SetLoaderMount(std::move(loader_mount)); } else { context = LoaderContext::Builder() .SetLoaderInfo(std::move(info)) .SetLoaderId(loader_id) - .SetActive(); + .SetActive() + .SetLoaderMount(std::move(loader_mount)); } } catch (const Exception& e) { _E("Exception occurs. error(%s)", e.what()); @@ -109,7 +111,7 @@ std::shared_ptr LoaderFactory::CreateLoaderContext( } std::shared_ptr LoaderFactory::CreateLoaderContext( - tizen_base::Bundle b) { + tizen_base::Bundle b, std::shared_ptr loader_mount) { auto caller_pid = b.GetString(kAulCallerPid); if (caller_pid.empty()) return nullptr; @@ -126,7 +128,8 @@ std::shared_ptr LoaderFactory::CreateLoaderContext( .SetLoaderInfo(std::move(loader_info)) .SetLoaderId(loader_id) .SetCallerPid(std::stoi(caller_pid)) - .SetActive(); + .SetActive() + .SetLoaderMount(std::move(loader_mount)); if (context == nullptr) return nullptr; } catch (const Exception& e) { @@ -138,7 +141,8 @@ std::shared_ptr LoaderFactory::CreateLoaderContext( } std::shared_ptr LoaderFactory::CreateLoaderContext( - LoaderInfoPtr info, pid_t caller_pid) { + LoaderInfoPtr info, pid_t caller_pid, + std::shared_ptr loader_mount) { int loader_id = MakeDynamicLoaderId(); LoaderContext* context; try { @@ -146,7 +150,8 @@ std::shared_ptr LoaderFactory::CreateLoaderContext( .SetLoaderInfo(std::move(info)) .SetLoaderId(loader_id) .SetCallerPid(caller_pid) - .SetActive(); + .SetActive() + .SetLoaderMount(std::move(loader_mount)); if (context == nullptr) return nullptr; } catch (const Exception& e) { diff --git a/src/launchpad-process-pool/loader_factory.hh b/src/launchpad-process-pool/loader_factory.hh index f44da2c..2208c82 100644 --- a/src/launchpad-process-pool/loader_factory.hh +++ b/src/launchpad-process-pool/loader_factory.hh @@ -36,10 +36,13 @@ class LoaderFactory { static LoaderFactory& GetInst(); - std::shared_ptr CreateLoaderContext(LoaderInfoPtr info); - std::shared_ptr CreateLoaderContext(tizen_base::Bundle b); - std::shared_ptr CreateLoaderContext(LoaderInfoPtr info, - pid_t caller_pid); + std::shared_ptr CreateLoaderContext( + LoaderInfoPtr info, std::shared_ptr loader_mount); + std::shared_ptr CreateLoaderContext( + tizen_base::Bundle b, std::shared_ptr loader_mount); + std::shared_ptr CreateLoaderContext( + LoaderInfoPtr info, pid_t caller_pid, + std::shared_ptr loader_mount); private: LoaderFactory() = default; diff --git a/src/launchpad-process-pool/loader_manager.cc b/src/launchpad-process-pool/loader_manager.cc index 472d556..7632d39 100644 --- a/src/launchpad-process-pool/loader_manager.cc +++ b/src/launchpad-process-pool/loader_manager.cc @@ -43,6 +43,7 @@ void LoaderManager::Dispose() { if (disposed_) return; + loader_mount_.reset(); hwacc_config_.reset(); app_defined_loader_info_manager_.reset(); loader_info_manager_.reset(); @@ -65,6 +66,11 @@ void LoaderManager::Init() { app_defined_loader_info_manager_.reset(new AppDefinedLoaderInfoManager()); app_defined_loader_info_manager_->SetEventListener(this); hwacc_config_.reset(new HWAccelerationConfig()); + + if (!label_monitor.IsDisposed()) { + setenv("LOADER_MOUNT", "1", 1); + loader_mount_.reset(new LoaderMount()); + } } catch (const Exception& e) { _E("Exception occurs. error: %s", e.what()); return; @@ -73,6 +79,12 @@ void LoaderManager::Init() { disposed_ = false; } +void LoaderManager::PrepareApp(const std::shared_ptr& context, + const AppInfo* app_info) { + pid_t pid = context->GetPid(); + loader_mount_->Mount(pid, app_info); +} + void LoaderManager::SetEventListener(LoaderManager::IEvent* event_listener) { event_listener_ = event_listener; } @@ -94,6 +106,7 @@ void LoaderManager::HandleSigchld(pid_t pid) { RemoveLoaderContextsByCallerPid(pid); LoaderExecutor::GetInst().HandleSigchld(pid); + if (loader_mount_) loader_mount_->HandleSigchld(pid); } void LoaderManager::AddDefaultLoaderContexts() { @@ -101,7 +114,8 @@ void LoaderManager::AddDefaultLoaderContexts() { loader_info_manager_->Load(); for (auto& info : loader_info_manager_->GetLoaderInfoList()) { - auto context = LoaderFactory::GetInst().CreateLoaderContext(info); + auto context = + LoaderFactory::GetInst().CreateLoaderContext(info, loader_mount_); if (context != nullptr) { context->SetEventListener(this); loader_contexts_.push_back(std::move(context)); @@ -148,7 +162,8 @@ std::shared_ptr LoaderManager::PrepareAppDefinedLoaderContext( auto context = FindLoaderContextFromName(name); if (context == nullptr) { - context = LoaderFactory::GetInst().CreateLoaderContext(info, caller_pid); + context = LoaderFactory::GetInst().CreateLoaderContext(info, caller_pid, + loader_mount_); if (context == nullptr) { _E("Failed to create loader context. loader_name: %s", name.c_str()); @@ -166,7 +181,8 @@ std::shared_ptr LoaderManager::PrepareAppDefinedLoaderContext( std::shared_ptr LoaderManager::AddLoaderContext( tizen_base::Bundle b) { - auto context = LoaderFactory::GetInst().CreateLoaderContext(std::move(b)); + auto context = + LoaderFactory::GetInst().CreateLoaderContext(std::move(b), loader_mount_); if (context == nullptr) return nullptr; diff --git a/src/launchpad-process-pool/loader_manager.hh b/src/launchpad-process-pool/loader_manager.hh index 7f3f078..060c2c3 100644 --- a/src/launchpad-process-pool/loader_manager.hh +++ b/src/launchpad-process-pool/loader_manager.hh @@ -26,6 +26,7 @@ #include #include +#include #include #include "launchpad-process-pool/app_defined_loader_info_manager.hh" @@ -33,6 +34,7 @@ #include "launchpad-process-pool/hydra_loader_context.hh" #include "launchpad-process-pool/loader_context.hh" #include "launchpad-process-pool/loader_info.hh" +#include "launchpad-process-pool/loader_mount.hh" #include "launchpad-process-pool/memory_monitor.hh" #include "launchpad-process-pool/sequencer.hh" @@ -59,6 +61,8 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent, static LoaderManager& GetInst(); void Dispose(); + void PrepareApp(const std::shared_ptr& context, + const AppInfo* app_info); void SetEventListener(IEvent* event_listener); void HandleSigchld(pid_t pid); void AddDefaultLoaderContexts(); @@ -117,6 +121,7 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent, std::unique_ptr app_defined_loader_info_manager_; std::vector> loader_contexts_; std::unique_ptr hwacc_config_; + std::shared_ptr loader_mount_; }; } // namespace launchpad diff --git a/src/launchpad-process-pool/loader_mount.cc b/src/launchpad-process-pool/loader_mount.cc new file mode 100644 index 0000000..db264e8 --- /dev/null +++ b/src/launchpad-process-pool/loader_mount.cc @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-process-pool/loader_mount.hh" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "launchpad-process-pool/launchpad_args.hh" +#include "launchpad-process-pool/log_private.hh" + +namespace fs = std::filesystem; +namespace { + +bool IsExceptable(const std::string& path) { + static char buf[PATH_MAX]; + ssize_t len = readlink(path.c_str(), buf, sizeof(buf)); + if (len < 0) { + _E("readlink() is failed. errno: %d", errno); + return false; + } + + buf[len] = '\0'; + if (strstr(buf, "log") != nullptr || + strstr(buf, "trace") != nullptr || + strstr(buf, "dev") != nullptr) + return true; + + return false; +} + +std::vector GetExceptableFds() { + std::vector fds; + try { + fs::path proc_path("/proc/self/fd"); + for (const auto& entry : fs::directory_iterator(proc_path)) { + if (!isdigit(entry.path().filename().string()[0])) + continue; + + int fd = std::stoi(entry.path().filename().string()); + if (dlog_is_log_fd(fd) || IsExceptable(entry.path().string())) + fds.push_back(fd); + } + } catch (const fs::filesystem_error& e) { + _E("Exception occurs. error(%s)", e.what()); + } + + return fds; +} + +int ChangeMountNamespace(pid_t pid) { + std::string mnt_path = "/proc/" + std::to_string(pid) + "/ns/mnt"; + int fd = open(mnt_path.c_str(), O_RDONLY); + if (fd < 0) { + _E("open() is failed. path(%s), errno(%d)", mnt_path.c_str(), errno); + return -1; + } + + int ret = ::setns(fd, 0); + close(fd); + if (ret != 0) { + _E("setns() is failed. path(%s), errno(%d)", mnt_path.c_str(), errno); + return -1; + } + + _D("setns() is successful. pid(%d)", pid); + return 0; +} + +class Request : public tizen_base::Parcelable { + public: + explicit Request(tizen_base::Parcel* parcel) { ReadFromParcel(parcel); } + + Request(pid_t pid, tizen_base::Bundle b) : pid_(pid), b_(std::move(b)) {} + + pid_t GetPid() const { return pid_; } + + const tizen_base::Bundle& GetBundle() const { return b_; } + + void WriteToParcel(tizen_base::Parcel* parcel) const override { + parcel->WriteInt32(pid_); + bundle_raw* raw = nullptr; + int len = 0; + bundle_encode(b_.GetHandle(), &raw, &len); + parcel->WriteInt32(len); + parcel->Write(reinterpret_cast(raw), len); + bundle_free_encoded_rawdata(&raw); + } + + void ReadFromParcel(tizen_base::Parcel* parcel) override { + parcel->ReadInt32(&pid_); + int len = 0; + parcel->ReadInt32(&len); + if (len > 0) { + std::vector data(len); + parcel->Read(data.data(), data.size()); + b_ = tizen_base::Bundle( + bundle_decode(reinterpret_cast(data.data()), len), false, + true); + } + } + + private: + pid_t pid_; + tizen_base::Bundle b_; +}; + +class Reply : public tizen_base::Parcelable { + public: + explicit Reply(tizen_base::Parcel* parcel) { ReadFromParcel(parcel); } + + explicit Reply(int result) : result_(result) {} + + int GetResult() const { return result_; } + + void WriteToParcel(tizen_base::Parcel* parcel) const override { + parcel->WriteInt32(result_); + } + + void ReadFromParcel(tizen_base::Parcel* parcel) override { + parcel->ReadInt32(&result_); + } + + private: + int result_ = -1; +}; + +} // namespace + +namespace launchpad { + +LoaderMount::LoaderMount() : Executor(this), launchpad_ppid_(getppid()) { + Prepare(); +} + +LoaderMount::~LoaderMount() { Dispose(); } + +void LoaderMount::Prepare() { + if (pid_ > 0) return; + + int pipe_fd[2]; + if (CreatePipe(&pipe_fd) != 0) return; + + read_socket_.reset(new Socket(pipe_fd[0])); + int write_fd = pipe_fd[1]; + + if (CreatePipe(&pipe_fd) != 0) return; + + int read_fd = pipe_fd[0]; + write_socket_.reset(new Socket(pipe_fd[1])); + + _W("read_socket=%d, write_socket=%d", + read_socket_->GetFd(), write_socket_->GetFd()); + pid_ = Executor::Execute(); + if (pid_ == -1) { + _E("Failed to fork process. errno(%d)", errno); + close(read_fd); + close(write_fd); + return; + } + + read_socket_.reset(new Socket(read_fd)); + write_socket_.reset(new Socket(write_fd)); +} + +void LoaderMount::Dispose() { + read_socket_.reset(); + write_socket_.reset(); + if (pid_ > 0) { + if (kill(pid_, SIGKILL) == -1) + _E("Failed to send kill signal. pid(%d), errno(%d)", pid_, errno); + + pid_ = -1; + } +} + +void LoaderMount::HandleSigchld(pid_t pid) { + if (pid_ != pid) return; + + pid_ = -1; + Dispose(); + Prepare(); +} + +int LoaderMount::Mount(pid_t pid, const AppInfo* app_info) { + auto& b = app_info->GetBundle(); + if (b.GetType(kAulMountGadgetPaths) == BUNDLE_TYPE_NONE) return 0; + + tizen_base::Parcel parcel; + Request request(pid, b); + request.WriteToParcel(&parcel); + + _W("Send mount request"); + int ret = Write(parcel); + if (ret != 0) return ret; + + parcel.Clear(); + ret = Read(&parcel); + if (ret!= 0) return ret; + + _W("receive result"); + Reply reply(&parcel); + return reply.GetResult(); +} + +void LoaderMount::OnExecution() { + _D("Mount Manager"); + char** args = LaunchpadArgs::GetInst().GetArgs(); + size_t length = strlen(args[0]); + memset(args[0], '\0', length); + snprintf(args[0], length, "/usr/bin/loader-mount"); + + std::vector except_fds = GetExceptableFds(); + except_fds.push_back(read_socket_->GetFd()); + except_fds.push_back(write_socket_->GetFd()); + Util::CloseAllFds(except_fds); + int ret = ProcessRequests(); + exit(ret); +} + + +int LoaderMount::CreatePipe(int (*pipe_fd)[2]) { + *pipe_fd[0] = -1; + *pipe_fd[2] = -1; + + if (pipe(*pipe_fd) == -1) { + _E("pipe() is failed. errno(%d)", errno); + return -1; + } + + if (fcntl(*pipe_fd[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1) + _E("Failed to set pipe size. errno(%d)", errno); + + if (fcntl(*pipe_fd[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1) + _E("Failed to set pipe size. errno(%d)", errno); + + return 0; +} + +int LoaderMount::Write(const tizen_base::Parcel& parcel) { + size_t data_size = parcel.GetDataSize(); + int ret = + write_socket_->Write(static_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + _E("Write() is failed. error(%d)", ret); + return -1; + } + + return write_socket_->Write(parcel.GetData(), parcel.GetDataSize()); +} + +int LoaderMount::Read(tizen_base::Parcel* parcel) { + size_t data_size = 0; + int ret = + read_socket_->Read(static_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + _E("Read() is failed. error(%d)", ret); + return -1; + } + + std::vector data(data_size); + ret = read_socket_->Read(data.data(), data.size()); + if (ret != 0) { + _E("Read() is failed. error(%d)", ret); + return -1; + } + + parcel->Write(data.data(), data.size()); + return 0; +} + +int LoaderMount::ProcessRequests() { + tizen_base::Parcel parcel; + while (true) { + parcel.Clear(); + int ret = Read(&parcel); + if (ret != 0) continue; + + _W("Request received"); + Request request(&parcel); + ret = ChangeMountNamespace(request.GetPid()); + if (ret == 0) { + ret = Util::MountGadgetDirectories(request.GetBundle()); + ChangeMountNamespace(launchpad_ppid_); + } + + Reply reply(ret); + parcel.Clear(); + reply.WriteToParcel(&parcel); + Write(parcel); + } + + return 0; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/loader_mount.hh b/src/launchpad-process-pool/loader_mount.hh new file mode 100644 index 0000000..6bc2274 --- /dev/null +++ b/src/launchpad-process-pool/loader_mount.hh @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LAUNCHPAD_PROCESS_POOL_LOADER_MOUNT_HH_ +#define LAUNCHPAD_PROCESS_POOL_LOADER_MOUNT_HH_ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "launchpad-process-pool/executor.hh" + +namespace launchpad { + +class LoaderMount : public Executor::Delegator, public Executor { + public: + LoaderMount(); + virtual ~LoaderMount(); + + void Prepare(); + void Dispose(); + void HandleSigchld(pid_t pid); + + int Mount(pid_t pid, const AppInfo* app_info); + + private: + void OnExecution() override; + int CreatePipe(int (*pipe_fd)[2]); + int Write(const tizen_base::Parcel& parcel); + int Read(tizen_base::Parcel* parcel); + int ProcessRequests(); + + private: + pid_t launchpad_ppid_ = -1; + pid_t pid_ = -1; + std::unique_ptr read_socket_; + std::unique_ptr write_socket_; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_LOADER_MOUNT_HH_ diff --git a/src/lib/launchpad-common/aul_keys.hh b/src/lib/launchpad-common/aul_keys.hh index 61e1a69..b923aa4 100644 --- a/src/lib/launchpad-common/aul_keys.hh +++ b/src/lib/launchpad-common/aul_keys.hh @@ -54,6 +54,8 @@ constexpr const char kAulTaskManage[] = "__AUL_TASKMANAGE__"; constexpr const char kAulTepPath[] = "__AUL_TEP_PATH__"; constexpr const char kAulWaylandDisplay[] = "__AUL_WAYLAND_DISPLAY__"; constexpr const char kAulWaylandWorkingDir[] = "__AUL_WAYLAND_WORKING_DIR__"; +constexpr const char kAulMountGadgetPaths[] = "__AUL_MOUNT_GADGET_PATHS__"; +constexpr const char kAulMountGadgetPkgIds[] = "__AUL_MOUNT_GADGET_PKGIDS__"; } // namespace launchpad diff --git a/src/lib/launchpad-glib/util.cc b/src/lib/launchpad-glib/util.cc index e13ff46..b5861f6 100644 --- a/src/lib/launchpad-glib/util.cc +++ b/src/lib/launchpad-glib/util.cc @@ -95,6 +95,20 @@ void SetRegionFormatEnvironments() { setenv("LC_IDENTIFICATION", region, 1); } +void SetGadgetPkgIdsEnvironments(const tizen_base::Bundle& b) { + auto gadget_pkgids = b.GetStringArray(kAulMountGadgetPkgIds); + if (gadget_pkgids.empty()) return; + + std::string pkgids; + for (auto& pkgid : gadget_pkgids) { + if (!pkgids.empty()) pkgids += ":"; + + pkgids += pkgid; + } + + setenv("GADGET_PKGIDS", pkgids.c_str(), 1); +} + #ifdef TIZEN_FEATURE_SET_PERSONALITY_32 static void SetExecutionDomain() { int ret = personality(PER_LINUX32); @@ -241,7 +255,7 @@ class TepMountChecker : public DBus { std::vector paths_; }; -void MountDirectories(const std::vector& srcs, +int MountDirectories(const std::vector& srcs, const std::string& dest) { std::string opt = "lowerdir=" + dest; for (auto& src : srcs) @@ -251,6 +265,8 @@ void MountDirectories(const std::vector& srcs, int ret = mount(nullptr, dest.c_str(), "overlay", MS_RDONLY, opt.c_str()); if (ret != 0) _E("mount() is failed. dest(%s), errno(%d)", dest.c_str(), errno); + + return ret; } class ExternalPackage : public DBus { @@ -407,6 +423,7 @@ void Util::SetEnvironments(const AppInfo* app_info) { setenv("GCOV_PREFIX", "/tmp", 1); setenv("DALI_DISABLE_PARTIAL_UPDATE", "0", 1); + SetGadgetPkgIdsEnvironments(b); } void Util::DeleteSocketPath(pid_t pid, uid_t uid) { @@ -467,6 +484,16 @@ int Util::MountResourceDirectories(const AppInfo* app_info) { return 0; } +int Util::MountGadgetDirectories(const tizen_base::Bundle& b) { + auto gadget_paths = b.GetStringArray(kAulMountGadgetPaths); + if (!gadget_paths.empty()) { + auto root_path = b.GetString(kAulRootPath); + return MountDirectories(gadget_paths, root_path + "/bin"); + } + + return 0; +} + int Util::WaitTepMount(const AppInfo* app_info) { if (app_info->GetBundle().GetType(kAulTepPath) == BUNDLE_TYPE_NONE) return 0; diff --git a/src/lib/launchpad-glib/util.hh b/src/lib/launchpad-glib/util.hh index 07713ac..fa490fa 100644 --- a/src/lib/launchpad-glib/util.hh +++ b/src/lib/launchpad-glib/util.hh @@ -41,6 +41,7 @@ class EXPORT_API Util { static void DeleteSocketPath(pid_t pid, uid_t uid); static int EnableExternalPackage(const AppInfo* app_info); static int MountResourceDirectories(const AppInfo* app_info); + [[nodiscard]] static int MountGadgetDirectories(const tizen_base::Bundle& b); static int WaitTepMount(const AppInfo* app_info); static std::string GetLibDirectory(const std::string& app_path); static void CloseAllFds(const std::vector& except_fds = {}); diff --git a/src/lib/launchpad/step_prepare_execution.cc b/src/lib/launchpad/step_prepare_execution.cc index 1c19ce0..7da7fa3 100644 --- a/src/lib/launchpad/step_prepare_execution.cc +++ b/src/lib/launchpad/step_prepare_execution.cc @@ -98,6 +98,13 @@ int StepPrepareExecution::TrustAnchorLaunch(AppInfo* app_info) { } int StepPrepareExecution::MountResourceDirectories(AppInfo* app_info) { + if (getenv("LOADER_MOUNT") == nullptr) { + if (Util::MountGadgetDirectories(app_info->GetBundle()) != 0) { + _E("Failed to mount gadget resources"); + return -1; + } + } + int ret = Util::MountResourceDirectories(app_info); if (ret < 0) { _E("Failed to mount resource direstories. error: %d", ret); -- 2.7.4