2 * Copyright (c) 2015 - 2019 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.
20 #include <sys/socket.h>
22 #include <sys/types.h>
23 #include <sys/prctl.h>
25 #include <bundle_internal.h>
27 #include <security-manager.h>
28 #include <trust-anchor.h>
33 #include <sys/types.h>
36 #include "launchpad.h"
37 #include "launchpad_common.h"
38 #include "launchpad_types.h"
42 #define API __attribute__ ((visibility("default")))
45 #define AUL_PR_NAME 16
47 static loader_lifecycle_callback_s *__loader_callbacks;
48 static loader_adapter_s *__loader_adapter;
49 static void *__loader_user_data;
52 static bundle *__bundle;
53 static int __loader_type = LAUNCHPAD_TYPE_UNSUPPORTED;
54 static int __loader_id;
55 static bool __loop_quit;
57 static void __at_exit_to_release_bundle(void)
60 bundle_free(__bundle);
63 static int __prepare_exec(const char *appid, const char *app_path,
64 const char *pkg_type, int type, const char* pkgid,
65 const char *root_path, bool global, bundle *kb)
67 const char *file_name = NULL;
68 char process_name[AUL_PR_NAME] = { 0, };
70 struct buxton_client *bxt_cli;
72 __preexec_run(pkg_type, appid, app_path);
74 ret = _enable_external_pkg(kb, pkgid, global ? GLOBAL_USER : getuid());
79 SECURE_LOGD("[candidata] appid : %s / pkg_type : %s / app_path : %s",
80 appid, pkg_type, app_path);
83 ret = trust_anchor_launch(pkgid, GLOBAL_USER);
85 ret = trust_anchor_launch(pkgid, getuid());
87 if (ret != TRUST_ANCHOR_ERROR_NONE &&
88 ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
89 _E("trust_anchor_launch() returns %d", ret);
93 ret = _mount_res_dir(root_path, kb);
97 _W("security_manager_prepare_app ++");
98 ret = security_manager_prepare_app(appid);
99 _W("security_manager_prepare_app --");
100 if (ret != SECURITY_MANAGER_SUCCESS) {
101 _E("Failed to set privileges %s:%d", appid, ret);
105 _setup_stdio(basename(app_path));
107 ret = buxton_open(&bxt_cli, NULL, NULL);
109 _E("buxton_open() failed, errno(%d)", errno);
112 ret = buxton_update_client_label_sync(bxt_cli);
114 _E("buxton_update_client_label() failed, errno(%d)", errno);
115 buxton_close(bxt_cli);
118 buxton_close(bxt_cli);
121 * SET DUMPABLE - for coredump
122 * This dumpable flag should be set after
123 * calling perm_app_set_privilege().
125 prctl(PR_SET_DUMPABLE, 1);
127 /* SET PROCESS NAME*/
128 if (app_path == NULL) {
129 _D("app_path should not be NULL - check menu db");
133 file_name = strrchr(app_path, '/');
134 if (file_name == NULL) {
135 _D("file_name is NULL");
140 if (*file_name == '\0') {
141 _D("can't locate file name to execute");
145 memset(process_name, '\0', AUL_PR_NAME);
146 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
147 prctl(PR_SET_NAME, process_name);
149 ret = _wait_tep_mount(kb);
153 ret = _prepare_app_socket();
157 ret = _prepare_id_file();
161 _send_cmd_to_amd(APP_STARTUP_SIGNAL);
165 static int __default_launch_cb(bundle *kb, const char *appid,
166 const char *app_path, const char *root_path,
167 const char *pkgid, const char *pkg_type, int loader_type, bool global)
169 char err_str[MAX_LOCAL_BUFSZ] = { 0, };
172 r = __prepare_exec(appid, app_path, pkg_type, loader_type, pkgid,
173 root_path, global, kb);
175 _E("__candidate_process_prepare_exec() failed");
176 if (access(app_path, F_OK | R_OK)) {
177 SECURE_LOGE("access() failed for file: \"%s\", " \
178 "error: %d (%s)", app_path, errno,
179 strerror_r(errno, err_str, sizeof(err_str)));
187 static int __candidate_process_launchpad_main_loop(app_pkt_t *pkt,
188 char *out_app_path, int *out_argc, char ***out_argv, int type)
191 appinfo_t *menu_info = NULL;
192 const char *app_path = NULL;
194 char **tmp_argv = NULL;
198 kb = bundle_decode(pkt->data, pkt->len);
200 _E("bundle decode error");
204 if (__bundle != NULL)
205 bundle_free(__bundle);
208 atexit(__at_exit_to_release_bundle);
210 menu_info = _appinfo_create(kb);
211 if (menu_info == NULL) {
212 _D("such pkg no found");
216 if (menu_info->appid == NULL) {
217 _E("Unable to get app_id");
222 _E("Invalid launchpad type: %d", type);
226 SECURE_LOGD("app id: %s, launchpad type: %d", menu_info->appid, type);
228 app_path = _appinfo_get_app_path(menu_info);
229 if (app_path == NULL) {
230 _E("app_path is NULL");
234 if (app_path[0] != '/') {
235 _E("app_path is not absolute path");
239 _modify_bundle(kb, /*cr.pid - unused parameter*/ 0, menu_info,
242 if (menu_info->pkgid == NULL) {
243 _E("unable to get pkg_id from menu_info");
247 SECURE_LOGD("pkg id: %s", menu_info->pkgid);
249 /* Set environments */
250 _set_env(menu_info, kb);
252 tmp_argv = _create_argc_argv(kb, &tmp_argc);
254 if (__loader_callbacks->prelaunch) {
255 ret = __loader_callbacks->prelaunch(tmp_argc, tmp_argv,
256 app_path, menu_info->appid, menu_info->pkgid,
257 menu_info->pkg_type, __loader_user_data);
260 _E("prelaunch callback fail (%d)", ret);
265 __default_launch_cb(kb, menu_info->appid, app_path,
266 menu_info->root_path, menu_info->pkgid,
267 menu_info->pkg_type, type, menu_info->global);
269 if (__loader_callbacks->launch) {
270 ret = __loader_callbacks->launch(tmp_argc, tmp_argv, app_path,
271 menu_info->appid, menu_info->pkgid,
272 menu_info->pkg_type, __loader_user_data);
275 if (out_app_path != NULL && out_argc != NULL && out_argv != NULL) {
276 memset(out_app_path, '\0', strlen(out_app_path));
277 snprintf(out_app_path, LOADER_ARG_LEN, "%s", app_path);
279 *out_argv = tmp_argv;
280 *out_argc = tmp_argc;
281 (*out_argv)[LOADER_ARG_PATH] = out_app_path;
283 for (i = 0; i < *out_argc; i++) {
284 SECURE_LOGD("input argument %d : %s##", i,
291 if (menu_info != NULL)
292 _appinfo_free(menu_info);
295 bundle_free(__bundle);
302 static void __receiver_cb(int fd)
307 _D("[candidate] ECORE_FD_READ");
308 pkt = _recv_pkt_raw(fd);
310 _D("[candidate] _recv_pkt_raw error!");
314 __loader_adapter->remove_fd(__loader_user_data, fd);
316 ret = __candidate_process_launchpad_main_loop(pkt,
317 __argv[LOADER_ARG_PATH], &__argc, &__argv,
319 SECURE_LOGD("[candidate] real app argv[0]: %s, real app argc: %d",
320 __argv[LOADER_ARG_PATH], __argc);
324 __loader_adapter->loop_quit(__loader_user_data);
325 _D("[candidate] ecore main loop quit");
330 static void __update_lang(keynode_t *node, void *user_data)
334 lang = vconf_keynode_get_str(node);
336 _E("Failed to get language");
340 setenv("LANG", lang, 1);
343 static void __region_format_changed_cb(keynode_t *node, void *user_data)
347 region = vconf_keynode_get_str(node);
349 _E("Failed to get regionformat");
353 setenv("LC_CTYPE", region, 1);
356 static int __before_loop(int argc, char **argv)
360 bundle *extra = NULL;
363 if (_verify_proc_caps() < 0)
366 __preexec_init(argc, argv);
368 /* Set new session ID & new process group ID*/
369 /* In linux, child can set new session ID without check permission */
370 /* TODO : should be add to check permission in the kernel*/
373 memset(argv[LOADER_ARG_TYPE], 0, strlen(argv[LOADER_ARG_TYPE]));
374 memset(argv[LOADER_ARG_ID], 0, strlen(argv[LOADER_ARG_ID]));
376 extra = bundle_decode((bundle_raw *)argv[LOADER_ARG_EXTRA],
377 strlen(argv[LOADER_ARG_EXTRA]));
378 memset(argv[LOADER_ARG_EXTRA], 0,
379 strlen(argv[LOADER_ARG_EXTRA]));
382 if (__loader_callbacks->create) {
383 __loader_callbacks->create(extra, __loader_type,
393 client_fd = _connect_to_launchpad(__loader_type, __loader_id);
394 if (client_fd == -1) {
395 _D("Connecting to candidate process was failed.");
399 __loader_adapter->add_fd(__loader_user_data, client_fd, __receiver_cb);
401 r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
403 _E("Failed to register callback for langset. error(%d)", r);
405 r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT,
406 __region_format_changed_cb, NULL);
408 _E("Failed to register callback for regionformat. error(%d)", r);
413 static int __after_loop(void)
415 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT,
416 __region_format_changed_cb);
417 vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang);
419 if (__loader_callbacks->terminate) {
420 return __loader_callbacks->terminate(__argc, __argv,
427 API bundle *launchpad_loader_get_bundle(void)
432 API int launchpad_loader_main(int argc, char **argv,
433 loader_lifecycle_callback_s *callbacks,
434 loader_adapter_s *adapter, void *user_data)
439 _E("too few argument.");
443 is_hydra = argv[LOADER_ARG_HYDRA][0] - '0';
446 _D("Cannot run in hydra mode");
450 __loader_type = atoi(argv[LOADER_ARG_TYPE]);
451 if (__loader_type < 0 || __loader_type >= LAUNCHPAD_TYPE_MAX) {
452 _E("invalid argument. (type: %d)", __loader_type);
456 __loader_id = atoi(argv[LOADER_ARG_ID]);
458 if (callbacks == NULL) {
459 _E("invalid argument. callback is null");
463 if (adapter == NULL) {
464 _E("invalid argument. adapter is null");
468 if (adapter->loop_begin == NULL || adapter->loop_quit == NULL
469 || adapter->add_fd == NULL || adapter->remove_fd == NULL) {
470 _E("invalid argument. adapter callback is null");
474 __loader_callbacks = callbacks;
475 __loader_adapter = adapter;
476 __loader_user_data = user_data;
480 if (__before_loop(argc, argv) != 0) {
481 _E("Failed to prepare running loader. type(%d)", __loader_type);
485 _D("[candidate] ecore main loop begin");
486 __loader_adapter->loop_begin(__loader_user_data);
489 _E("[candidate] loop was stopped forcedly");
493 return __after_loop();
496 API int launchpad_loader_set_priority(int prio)
498 return _set_priority(prio);