2 * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "launchpad-process-pool/app_executor.hh"
23 #include <sys/prctl.h>
24 #include <trust-anchor.h>
25 #include <tzplatform_config.h>
31 #include <aul_keys.hh>
35 #include <user_tracer.hh>
38 #include "launchpad-process-pool/config.hh"
39 #include "launchpad-process-pool/debug.hh"
40 #include "launchpad-process-pool/log_private.hh"
41 #include "launchpad-process-pool/signal_manager.hh"
44 namespace fs = std::filesystem;
47 void ExecuteEcho(const std::string& app_path, const std::string& error) {
49 const_cast<char*>("/usr/bin/echo"),
50 const_cast<char*>("Failed to execute a file. path:"),
51 const_cast<char*>(app_path.c_str()),
52 const_cast<char*>("error:"),
53 const_cast<char*>(error.c_str()),
62 AppExecutor::AppExecutor() : Executor(this) {
63 LauncherInfoInflator inflator;
64 launcher_infos_ = inflator.Inflate("/usr/share/aul");
66 prepare_funcs_.push_back(
67 std::bind(&AppExecutor::StepPluginPrepareApp, this));
68 prepare_funcs_.push_back(
69 std::bind(&AppExecutor::StepEnableExternalPackage, this));
70 prepare_funcs_.push_back(
71 std::bind(&AppExecutor::StepEnableTrustAnchor, this));
72 prepare_funcs_.push_back(
73 std::bind(&AppExecutor::StepMountResDir, this));
74 prepare_funcs_.push_back(
75 std::bind(&AppExecutor::StepChangeMountNamespace, this));
76 prepare_funcs_.push_back(
77 std::bind(&AppExecutor::StepSecurityPrepareApp, this));
78 prepare_funcs_.push_back(
79 std::bind(&AppExecutor::StepSetupStdio, this));
80 prepare_funcs_.push_back(
81 std::bind(&AppExecutor::StepSetDumpable, this));
82 prepare_funcs_.push_back(
83 std::bind(&AppExecutor::StepSetProcessName, this));
84 prepare_funcs_.push_back(
85 std::bind(&AppExecutor::StepSetEnvironments, this));
86 prepare_funcs_.push_back(
87 std::bind(&AppExecutor::StepWaitTepMount, this));
88 prepare_funcs_.push_back(
89 std::bind(&AppExecutor::StepPrepareAppSocketAndIdFile, this));
90 prepare_funcs_.push_back(
91 std::bind(&AppExecutor::StepSendStartupSignal, this));
93 auto& process_pool_config = Config::GetInst().GetProcessPool();
94 process_pool_ = std::unique_ptr<ProcessPool>(
95 new ProcessPool("app", process_pool_config.GetNumberOfProcesses(), this));
98 pid_t AppExecutor::Execute(const AppInfo* app_info) {
99 if (process_pool_->IsPrepared()) {
100 tizen_base::Parcel parcel;
101 parcel.WriteParcelable(*app_info);
102 pid_t pid = process_pool_->Execute(parcel);
107 app_info_ = app_info;
108 return Executor::Execute();
111 void AppExecutor::DisposeCandidateProcess() {
112 process_pool_->Dispose();
113 process_pool_->SetTimer();
116 void AppExecutor::HandleSigchld(pid_t pid) {
117 process_pool_->HandleSigchld(pid);
120 void AppExecutor::OnExecution() {
121 UserTracer::Print(std::to_string(getpid()) + "|after calling fork(). " +
122 app_info_->GetAppId());
123 CheckAndPrepareDebugging();
124 SignalManager::GetInst().UnblockSigchld();
125 Util::DeleteSocketPath(getpid(), getuid());
129 _E("Failed to prepare executing application(%s)",
130 app_info_->GetAppId().c_str());
131 ExecuteEcho(app_info_->GetAppPath(), std::to_string(ret));
135 std::vector<std::string> argv = CreateAppArgv(app_info_->GetAppPath(),
136 app_info_->GetBundle(), app_info_->GetAppType());
137 char** app_argv = static_cast<char**>(calloc(argv.size() + 1, sizeof(char*)));
138 if (app_argv == nullptr) {
140 ExecuteEcho(app_info_->GetAppPath(), std::to_string(-ENOMEM));
144 int app_argc = argv.size();
145 for (int i = 0; i < app_argc; ++i) {
146 app_argv[i] = const_cast<char*>(argv[i].c_str());
147 SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
150 auto lib_dir = Util::GetLibDirectory(app_info_->GetAppPath());
151 if (!lib_dir.empty())
152 setenv("LD_LIBRARY_PATH", lib_dir.c_str(), 1);
155 if (execv(app_argv[LoaderArg::Path], app_argv) < 0) {
157 fprintf(stderr, "Failed to execute a file. path: %s, errno: %d(%s)\n",
158 app_info_->GetAppPath().c_str(), errno,
159 strerror_r(errno, err_buf, sizeof(err_buf)));
160 ExecuteEcho(app_info_->GetAppPath(), err_buf);
165 void AppExecutor::OnRequestReceived(tizen_base::Parcel* parcel) {
166 _W("Request received");
168 parcel->ReadParcelable(&app_info);
169 app_info_ = &app_info;
173 int AppExecutor::Prepare() {
174 for (auto& func : prepare_funcs_) {
182 int AppExecutor::StepPluginPrepareApp() {
183 return Plugin::PrepareApp(app_info_->GetAppId(), app_info_->GetBundle());
186 int AppExecutor::StepEnableExternalPackage() {
187 return Util::EnableExternalPackage(app_info_);
190 int AppExecutor::StepEnableTrustAnchor() {
191 int ret = trust_anchor_launch(app_info_->GetPkgId().c_str(),
192 app_info_->IsGlobal() ? GLOBAL_USER : getuid());
193 if (ret != TRUST_ANCHOR_ERROR_NONE &&
194 ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
195 _E("trust_anchor_launch() returns %d", ret);
202 int AppExecutor::StepMountResDir() {
203 int ret = Util::MountGadgetDirectories(app_info_->GetBundle());
205 _E("Failed to mount gadget resources");
209 ret = Util::MountLibraryDirectories(app_info_->GetBundle());
211 _E("Failed to mount lib directories");
215 return Util::MountResourceDirectories(app_info_);
218 int AppExecutor::StepChangeMountNamespace() {
219 if (app_info_->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE)
220 Debug::ChangeMountNamespace();
225 int AppExecutor::StepSecurityPrepareApp() {
226 auto enabled_light_user = app_info_->GetBundle().GetString(
227 kAulEnabledLightUser);
228 _W("security_manager_prepare_app2 ++ %s", app_info_->GetAppId().c_str());
229 int ret = security_manager_prepare_app2(app_info_->GetAppId().c_str(),
230 enabled_light_user.empty() ? nullptr : enabled_light_user.c_str());
231 _W("security_manager_prepare_app2 -- %s", app_info_->GetAppId().c_str());
232 if (ret != SECURITY_MANAGER_SUCCESS) {
233 _E("security_manager_prepare_app2() returns %d", ret);
240 int AppExecutor::StepSetupStdio() {
241 if (app_info_->GetBundle().GetType(kAulSdk) == BUNDLE_TYPE_NONE)
247 int AppExecutor::StepSetDumpable() {
248 prctl(PR_SET_DUMPABLE, 1);
252 int AppExecutor::StepSetProcessName() {
253 fs::path file_path(app_info_->GetAppPath());
254 fs::path file_name = file_path.filename();
255 prctl(PR_SET_NAME, file_name.c_str());
259 int AppExecutor::StepSetEnvironments() {
260 Util::SetEnvironments(app_info_);
264 int AppExecutor::StepWaitTepMount() {
265 return Util::WaitTepMount(app_info_);
268 int AppExecutor::StepPrepareAppSocketAndIdFile() {
269 if (app_info_->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE)
272 if (Util::PrepareAppSocket() < 0)
275 return Util::PrepareAppIdFile(app_info_);
278 int AppExecutor::StepSendStartupSignal() {
279 Util::SendCmdToAmd(AmdCmd::AppStartupSignal);
283 void AppExecutor::CheckAndPrepareDebugging() {
284 auto& debug = Debug::GetInst();
285 auto& b = app_info_->GetBundle();
286 if (b.GetType(kAulSdk) != BUNDLE_TYPE_NONE)
287 debug.PrepareDebugger(b);
289 debug.CheckAndSetAsanActivation(app_info_->GetAppId());
290 debug.CheckWebAppDebugging(b);
293 std::vector<std::string> AppExecutor::GetLauncherArgv(
294 const std::string& app_type) {
295 std::vector<std::string> argv;
296 auto found = std::find_if(
297 launcher_infos_.begin(), launcher_infos_.end(),
298 [app_type](const launchpad::LauncherInfoPtr& info) -> bool {
299 return std::find_if(info->GetAppTypes().begin(),
300 info->GetAppTypes().end(),
301 [app_type](const std::string& type) -> bool {
302 return type == app_type;
303 }) != info->GetAppTypes().end();
305 if (found == launcher_infos_.end())
308 auto launcher_info = *found;
309 argv.insert(argv.end(), launcher_info->GetExe());
310 argv.insert(argv.end(), launcher_info->GetExtraArgs().begin(),
311 launcher_info->GetExtraArgs().end());
315 std::vector<std::string> AppExecutor::CreateAppArgv(const std::string& app_path,
316 const tizen_base::Bundle& b, const std::string& app_type) {
317 auto& inst = launchpad::Debug::GetInst();
318 std::vector<std::string> argv = inst.GetArgv();
319 if (inst.ShouldAttach())
322 auto launcher_argv = GetLauncherArgv(app_type);
323 if (!launcher_argv.empty())
324 argv.insert(argv.end(), launcher_argv.begin(), launcher_argv.end());
326 auto exported_argv = b.Export();
327 exported_argv[LoaderArg::Path] = app_path;
328 if (!exported_argv.empty())
329 argv.insert(argv.end(), exported_argv.begin(), exported_argv.end());
331 auto extra_argv = inst.GetExtraArgv();
332 if (!extra_argv.empty())
333 argv.insert(argv.end(), extra_argv.begin(), extra_argv.end());
338 } // namespace launchpad