2 * Copyright (c) 2015 - 2016 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 #ifdef _APPFW_FEATURE_LOADER_PRIORITY
27 #include <sys/resource.h>
29 #include <bundle_internal.h>
31 #include <security-manager.h>
33 #include "launchpad_common.h"
34 #include "launchpad.h"
38 #define API __attribute__ ((visibility("default")))
41 #define AUL_PR_NAME 16
42 #define LOWEST_PRIO 20
44 static loader_lifecycle_callback_s *__loader_callbacks;
45 static loader_adapter_s *__loader_adapter;
46 static void *__loader_user_data;
49 static bundle *__bundle;
50 static int __loader_type = LAUNCHPAD_TYPE_UNSUPPORTED;
51 static int __loader_id;
53 static void __at_exit_to_release_bundle(void)
56 bundle_free(__bundle);
59 static int __prepare_exec(const char *appid, const char *app_path,
60 const char *pkg_type, int type)
62 const char *file_name = NULL;
63 char process_name[AUL_PR_NAME] = { 0, };
66 __preexec_run(pkg_type, appid, app_path);
69 SECURE_LOGD("[candidata] appid : %s / pkg_type : %s / app_path : %s",
70 appid, pkg_type, app_path);
71 ret = security_manager_prepare_app(appid);
72 if (ret != SECURITY_MANAGER_SUCCESS) {
73 _D("fail to set privileges - " \
74 "check your package's credential: %d\n", ret);
79 * SET DUMPABLE - for coredump
80 * This dumpable flag should be set after
81 * calling perm_app_set_privilege().
83 prctl(PR_SET_DUMPABLE, 1);
86 if (app_path == NULL) {
87 _D("app_path should not be NULL - check menu db");
91 file_name = strrchr(app_path, '/');
92 if (file_name == NULL) {
93 _D("file_name is NULL");
98 if (*file_name == '\0') {
99 _D("can't locate file name to execute");
103 memset(process_name, '\0', AUL_PR_NAME);
104 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
105 prctl(PR_SET_NAME, process_name);
110 static int __default_launch_cb(bundle *kb, const char *appid,
111 const char *app_path, const char *root_path,
112 const char *pkgid, const char *pkg_type, int loader_type)
114 char err_str[MAX_LOCAL_BUFSZ] = { 0, };
116 #ifdef _APPFW_FEATURE_PRIORITY_CHANGE
118 const char *high_priority = bundle_get_val(kb, AUL_K_HIGHPRIORITY);
120 _D("high_priority: %s", high_priority);
121 if (strncmp(high_priority, "true", 4) == 0) {
122 res = setpriority(PRIO_PROCESS, 0, -10);
124 SECURE_LOGE("Setting process (%d) priority " \
125 "to -10 failed, errno: %d (%s)",
127 strerror_r(errno, err_str, sizeof(err_str)));
130 bundle_del(kb, AUL_K_HIGHPRIORITY);
133 ret = _mount_legacy_app_path(root_path, pkgid);
135 _W("Failed to mount legacy app path(%d)", errno);
137 if (__prepare_exec(appid, app_path, pkg_type, loader_type) < 0) {
138 _E("__candidate_process_prepare_exec() failed");
139 if (access(app_path, F_OK | R_OK)) {
140 SECURE_LOGE("access() failed for file: \"%s\", " \
141 "error: %d (%s)", app_path, errno,
142 strerror_r(errno, err_str, sizeof(err_str)));
150 static int __candidate_process_launchpad_main_loop(app_pkt_t *pkt,
151 char *out_app_path, int *out_argc, char ***out_argv, int type)
154 appinfo_t *menu_info = NULL;
155 const char *app_path = NULL;
157 char **tmp_argv = NULL;
161 kb = bundle_decode(pkt->data, pkt->len);
163 _E("bundle decode error");
167 if (__bundle != NULL)
168 bundle_free(__bundle);
171 atexit(__at_exit_to_release_bundle);
173 menu_info = _appinfo_create(kb);
174 if (menu_info == NULL) {
175 _D("such pkg no found");
179 if (menu_info->appid == NULL) {
180 _E("Unable to get app_id");
185 _E("Invalid launchpad type: %d", type);
189 SECURE_LOGD("app id: %s, launchpad type: %d", menu_info->appid, type);
191 app_path = _appinfo_get_app_path(menu_info);
192 if (app_path == NULL) {
193 _E("app_path is NULL");
197 if (app_path[0] != '/') {
198 _E("app_path is not absolute path");
202 _modify_bundle(kb, /*cr.pid - unused parameter*/ 0, menu_info,
205 if (menu_info->pkgid == NULL) {
206 _E("unable to get pkg_id from menu_info");
210 SECURE_LOGD("pkg id: %s", menu_info->pkgid);
212 tmp_argv = _create_argc_argv(kb, &tmp_argc);
214 __default_launch_cb(kb, menu_info->appid, app_path,
215 menu_info->root_path, menu_info->pkgid,
216 menu_info->pkg_type, type);
218 if (__loader_callbacks->launch) {
219 ret = __loader_callbacks->launch(tmp_argc, tmp_argv, app_path,
220 menu_info->appid, menu_info->pkgid,
221 menu_info->pkg_type, __loader_user_data);
225 _set_env(menu_info, kb);
227 if (out_app_path != NULL && out_argc != NULL && out_argv != NULL) {
228 memset(out_app_path, '\0', strlen(out_app_path));
229 snprintf(out_app_path, LOADER_ARG_LEN, "%s", app_path);
231 *out_argv = tmp_argv;
232 *out_argc = tmp_argc;
233 (*out_argv)[LOADER_ARG_PATH] = out_app_path;
235 for (i = 0; i < *out_argc; i++) {
236 SECURE_LOGD("input argument %d : %s##", i,
243 if (menu_info != NULL)
244 _appinfo_free(menu_info);
247 bundle_free(__bundle);
254 static void __receiver_cb(int fd)
260 _D("[candidate] ECORE_FD_READ");
261 pkt = (app_pkt_t *)malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
263 _D("[candidate] out of memory1");
266 memset(pkt, 0, AUL_SOCK_MAXBUFF);
268 recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
269 if (recv_ret == -1) {
270 _D("[condidate] recv error!");
275 _D("[candidate] recv_ret: %d, pkt->len: %d", recv_ret, pkt->len);
277 __loader_adapter->remove_fd(__loader_user_data, fd);
279 ret = __candidate_process_launchpad_main_loop(pkt,
280 __argv[LOADER_ARG_PATH], &__argc, &__argv,
282 SECURE_LOGD("[candidate] real app argv[0]: %s, real app argc: %d",
283 __argv[LOADER_ARG_PATH], __argc);
287 __loader_adapter->loop_quit(__loader_user_data);
288 _D("[candidate] ecore main loop quit");
292 static int __before_loop(int argc, char **argv)
296 bundle *extra = NULL;
297 #ifdef _APPFW_FEATURE_LOADER_PRIORITY
298 char err_str[MAX_LOCAL_BUFSZ] = { 0, };
299 int res = setpriority(PRIO_PROCESS, 0, LOWEST_PRIO);
302 SECURE_LOGE("Setting process (%d) priority to %d failed, " \
303 "errno: %d (%s)", getpid(), LOWEST_PRIO, errno,
304 strerror_r(errno, err_str, sizeof(err_str)));
307 __preexec_init(argc, argv);
309 /* Set new session ID & new process group ID*/
310 /* In linux, child can set new session ID without check permission */
311 /* TODO : should be add to check permission in the kernel*/
314 memset(argv[LOADER_ARG_TYPE], 0, strlen(argv[LOADER_ARG_TYPE]));
315 memset(argv[LOADER_ARG_ID], 0, strlen(argv[LOADER_ARG_ID]));
317 extra = bundle_decode((bundle_raw *)argv[LOADER_ARG_EXTRA],
318 strlen(argv[LOADER_ARG_EXTRA]));
319 memset(argv[LOADER_ARG_EXTRA], 0, strlen(argv[LOADER_ARG_EXTRA]));
322 if (__loader_callbacks->create) {
323 __loader_callbacks->create(extra, __loader_type,
332 #ifdef _APPFW_FEATURE_LOADER_PRIORITY
333 res = setpriority(PRIO_PGRP, 0, 0);
335 SECURE_LOGE("Setting process (%d) priority to 0 failed, " \
336 "errno: %d (%s)", getpid(), errno,
337 strerror_r(errno, err_str, sizeof(err_str)));
340 client_fd = _connect_to_launchpad(__loader_type, __loader_id);
341 if (client_fd == -1) {
342 _D("Connecting to candidate process was failed.");
346 __loader_adapter->add_fd(__loader_user_data, client_fd, __receiver_cb);
351 static int __after_loop(void)
353 if (__loader_callbacks->terminate) {
354 return __loader_callbacks->terminate(__argc, __argv,
361 bundle *launchpad_loader_get_bundle()
366 API int launchpad_loader_main(int argc, char **argv,
367 loader_lifecycle_callback_s *callbacks,
368 loader_adapter_s *adapter, void *user_data)
371 _E("too few argument.");
375 __loader_type = argv[LOADER_ARG_TYPE][0] - '0';
376 if (__loader_type < 0 || __loader_type >= LAUNCHPAD_TYPE_MAX) {
377 _E("invalid argument. (type: %d)", __loader_type);
381 __loader_id = atoi(argv[LOADER_ARG_ID]);
383 if (callbacks == NULL) {
384 _E("invalid argument. callback is null");
388 if (adapter == NULL) {
389 _E("invalid argument. adapter is null");
393 if (adapter->loop_begin == NULL || adapter->loop_quit == NULL
394 || adapter->add_fd == NULL || adapter->remove_fd == NULL) {
395 _E("invalid argument. adapter callback is null");
399 __loader_callbacks = callbacks;
400 __loader_adapter = adapter;
401 __loader_user_data = user_data;
405 if (__before_loop(argc, argv) != 0)
408 _D("[candidate] ecore main loop begin");
409 __loader_adapter->loop_begin(__loader_user_data);
411 return __after_loop();