Bump up efl module version.
[platform/core/appfw/launchpad.git] / src / launchpad_lib.c
1 /*
2  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #define _GNU_SOURCE
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/socket.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/prctl.h>
24 #include <malloc.h>
25 #include <bundle_internal.h>
26 #include <aul.h>
27 #include <security-manager.h>
28 #include <trust-anchor.h>
29 #include <buxton2.h>
30 #include <vconf.h>
31
32 #include "launchpad_common.h"
33 #include "launchpad.h"
34 #include "preexec.h"
35
36 #ifndef API
37 #define API __attribute__ ((visibility("default")))
38 #endif
39
40 #define AUL_PR_NAME 16
41
42 static loader_lifecycle_callback_s *__loader_callbacks;
43 static loader_adapter_s *__loader_adapter;
44 static void *__loader_user_data;
45 static int __argc;
46 static char **__argv;
47 static bundle *__bundle;
48 static int __loader_type = LAUNCHPAD_TYPE_UNSUPPORTED;
49 static int __loader_id;
50
51 static void __at_exit_to_release_bundle(void)
52 {
53         if (__bundle)
54                 bundle_free(__bundle);
55 }
56
57 static int __prepare_exec(const char *appid, const char *app_path,
58                         const char *pkg_type, int type, const char* pkgid,
59                         bool global, bundle *kb)
60 {
61         const char *file_name = NULL;
62         char process_name[AUL_PR_NAME] = { 0, };
63         int ret;
64         struct buxton_client *bxt_cli;
65
66         __preexec_run(pkg_type, appid, app_path);
67
68         ret = _enable_external_pkg(kb, pkgid, global ? GLOBAL_USER : getuid());
69         if (ret < 0)
70                 return -1;
71
72         /* SET PRIVILEGES*/
73         SECURE_LOGD("[candidata] appid : %s / pkg_type : %s / app_path : %s",
74                 appid, pkg_type, app_path);
75
76         if (global)
77                 ret = trust_anchor_launch(pkgid, GLOBAL_USER);
78         else
79                 ret = trust_anchor_launch(pkgid, getuid());
80
81         if (ret != TRUST_ANCHOR_ERROR_NONE &&
82                         ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) {
83                 _E("trust_anchor_launch() returns %d", ret);
84                 return -1;
85         }
86
87         _W("security_manager_prepare_app ++");
88         ret = security_manager_prepare_app(appid);
89         _W("security_manager_prepare_app --");
90         if (ret != SECURITY_MANAGER_SUCCESS) {
91                 _E("Failed to set privileges %s:%d", appid, ret);
92                 return -1;
93         }
94
95         _send_cmd_to_amd(APP_STARTUP_SIGNAL);
96         _setup_stdio(basename(app_path));
97
98         ret = buxton_open(&bxt_cli, NULL, NULL);
99         if (ret != 0) {
100                 _E("buxton_open() failed, errno(%d)", errno);
101                 return -1;
102         }
103         ret = buxton_update_client_label_sync(bxt_cli);
104         if (ret != 0) {
105                 _E("buxton_update_client_label() failed, errno(%d)", errno);
106                 buxton_close(bxt_cli);
107                 return -1;
108         }
109         buxton_close(bxt_cli);
110
111         /*
112          * SET DUMPABLE - for coredump
113          * This dumpable flag should be set after
114          * calling perm_app_set_privilege().
115          */
116         prctl(PR_SET_DUMPABLE, 1);
117
118         /* SET PROCESS NAME*/
119         if (app_path == NULL) {
120                 _D("app_path should not be NULL - check menu db");
121                 return -1;
122         }
123
124         file_name = strrchr(app_path, '/');
125         if (file_name == NULL) {
126                 _D("file_name is NULL");
127                 return -1;
128         }
129
130         file_name++;
131         if (*file_name == '\0') {
132                 _D("can't locate file name to execute");
133                 return -1;
134         }
135
136         memset(process_name, '\0', AUL_PR_NAME);
137         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
138         prctl(PR_SET_NAME, process_name);
139
140         ret = _wait_tep_mount(kb);
141         if (ret < 0)
142                 return -1;
143
144         ret = _prepare_app_socket();
145         if (ret < 0)
146                 return -1;
147
148         ret = _prepare_id_file();
149         if (ret < 0)
150                 return -1;
151
152         return 0;
153 }
154
155 static int __default_launch_cb(bundle *kb, const char *appid,
156                 const char *app_path, const char *root_path,
157                 const char *pkgid, const char *pkg_type, int loader_type, bool global)
158 {
159         char err_str[MAX_LOCAL_BUFSZ] = { 0, };
160         int r;
161
162         r = __prepare_exec(appid, app_path, pkg_type, loader_type, pkgid,
163                         global, kb);
164         if (r < 0) {
165                 _E("__candidate_process_prepare_exec() failed");
166                 if (access(app_path, F_OK | R_OK)) {
167                         SECURE_LOGE("access() failed for file: \"%s\", " \
168                                 "error: %d (%s)", app_path, errno,
169                                 strerror_r(errno, err_str, sizeof(err_str)));
170                 }
171                 exit(-1);
172         }
173
174         return 0;
175 }
176
177 static int __candidate_process_launchpad_main_loop(app_pkt_t *pkt,
178                 char *out_app_path, int *out_argc, char ***out_argv, int type)
179 {
180         bundle *kb;
181         appinfo_t *menu_info = NULL;
182         const char *app_path = NULL;
183         int tmp_argc = 0;
184         char **tmp_argv = NULL;
185         int ret = -1;
186         int i;
187
188         kb = bundle_decode(pkt->data, pkt->len);
189         if (!kb) {
190                 _E("bundle decode error");
191                 exit(-1);
192         }
193
194         if (__bundle != NULL)
195                 bundle_free(__bundle);
196
197         __bundle = kb;
198         atexit(__at_exit_to_release_bundle);
199
200         menu_info = _appinfo_create(kb);
201         if (menu_info == NULL) {
202                 _D("such pkg no found");
203                 exit(-1);
204         }
205
206         if (menu_info->appid == NULL) {
207                 _E("Unable to get app_id");
208                 exit(-1);
209         }
210
211         if (type < 0) {
212                 _E("Invalid launchpad type: %d", type);
213                 exit(-1);
214         }
215
216         SECURE_LOGD("app id: %s, launchpad type: %d", menu_info->appid, type);
217
218         app_path = _appinfo_get_app_path(menu_info);
219         if (app_path == NULL) {
220                 _E("app_path is NULL");
221                 exit(-1);
222         }
223
224         if (app_path[0] != '/') {
225                 _E("app_path is not absolute path");
226                 exit(-1);
227         }
228
229         _modify_bundle(kb, /*cr.pid - unused parameter*/ 0, menu_info,
230                         pkt->cmd);
231
232         if (menu_info->pkgid == NULL) {
233                 _E("unable to get pkg_id from menu_info");
234                 exit(-1);
235         }
236
237         SECURE_LOGD("pkg id: %s", menu_info->pkgid);
238
239         /* Set environments */
240         _set_env(menu_info, kb);
241
242         tmp_argv = _create_argc_argv(kb, &tmp_argc);
243
244         __default_launch_cb(kb, menu_info->appid, app_path,
245                         menu_info->root_path, menu_info->pkgid,
246                         menu_info->pkg_type, type, menu_info->global);
247
248         if (__loader_callbacks->launch) {
249                 ret = __loader_callbacks->launch(tmp_argc, tmp_argv, app_path,
250                                 menu_info->appid, menu_info->pkgid,
251                                 menu_info->pkg_type, __loader_user_data);
252         }
253
254         if (out_app_path != NULL && out_argc != NULL && out_argv != NULL) {
255                 memset(out_app_path, '\0', strlen(out_app_path));
256                 snprintf(out_app_path, LOADER_ARG_LEN, "%s", app_path);
257
258                 *out_argv = tmp_argv;
259                 *out_argc = tmp_argc;
260                 (*out_argv)[LOADER_ARG_PATH] = out_app_path;
261
262                 for (i = 0; i < *out_argc; i++) {
263                         SECURE_LOGD("input argument %d : %s##", i,
264                                         (*out_argv)[i]);
265                 }
266         } else {
267                 exit(-1);
268         }
269
270         if (menu_info != NULL)
271                 _appinfo_free(menu_info);
272
273         if (__bundle) {
274                 bundle_free(__bundle);
275                 __bundle = NULL;
276         }
277
278         return ret;
279 }
280
281 static void __receiver_cb(int fd)
282 {
283         int ret = -1;
284         app_pkt_t *pkt;
285
286         _D("[candidate] ECORE_FD_READ");
287         pkt = _recv_pkt_raw(fd);
288         if (!pkt) {
289                 _D("[candidate] _recv_pkt_raw error!");
290                 exit(-1);
291         }
292
293         __loader_adapter->remove_fd(__loader_user_data, fd);
294         close(fd);
295         ret = __candidate_process_launchpad_main_loop(pkt,
296                         __argv[LOADER_ARG_PATH], &__argc, &__argv,
297                         __loader_type);
298         SECURE_LOGD("[candidate] real app argv[0]: %s, real app argc: %d",
299                         __argv[LOADER_ARG_PATH], __argc);
300         free(pkt);
301
302         if (ret >= 0) {
303                 __loader_adapter->loop_quit(__loader_user_data);
304                 _D("[candidate] ecore main loop quit");
305         }
306 }
307
308 static void __update_lang(keynode_t *node, void *user_data)
309 {
310         char *lang = vconf_keynode_get_str(node);
311
312         if (lang)
313                 setenv("LANG", lang, 1);
314 }
315
316 static int __before_loop(int argc, char **argv)
317 {
318         int client_fd;
319         int ret = -1;
320         bundle *extra = NULL;
321
322         if (_verify_proc_caps() < 0)
323                 return -1;
324
325         __preexec_init(argc, argv);
326
327         /* Set new session ID & new process group ID*/
328         /* In linux, child can set new session ID without check permission */
329         /* TODO : should be add to check permission in the kernel*/
330         setsid();
331
332         memset(argv[LOADER_ARG_TYPE], 0, strlen(argv[LOADER_ARG_TYPE]));
333         memset(argv[LOADER_ARG_ID], 0, strlen(argv[LOADER_ARG_ID]));
334         if (argc > 3) {
335                 extra = bundle_decode((bundle_raw *)argv[LOADER_ARG_EXTRA],
336                                 strlen(argv[LOADER_ARG_EXTRA]));
337                 memset(argv[LOADER_ARG_EXTRA], 0,
338                                 strlen(argv[LOADER_ARG_EXTRA]));
339         }
340
341         if (__loader_callbacks->create) {
342                 __loader_callbacks->create(extra, __loader_type,
343                                 __loader_user_data);
344                 ret = 0;
345         }
346
347         if (extra)
348                 bundle_free(extra);
349
350         malloc_trim(0);
351
352         client_fd = _connect_to_launchpad(__loader_type, __loader_id);
353         if (client_fd == -1) {
354                 _D("Connecting to candidate process was failed.");
355                 return -1;
356         }
357
358         __loader_adapter->add_fd(__loader_user_data, client_fd, __receiver_cb);
359
360         if (vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL) != 0)
361                 _E("vconf_notify_key_changed failed");
362
363         return ret;
364 }
365
366 static int __after_loop(void)
367 {
368         vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang);
369
370         if (__loader_callbacks->terminate) {
371                 return __loader_callbacks->terminate(__argc, __argv,
372                                 __loader_user_data);
373         }
374
375         return -1;
376 }
377
378 bundle *launchpad_loader_get_bundle()
379 {
380         return __bundle;
381 }
382
383 API int launchpad_loader_main(int argc, char **argv,
384                 loader_lifecycle_callback_s *callbacks,
385                 loader_adapter_s *adapter, void *user_data)
386 {
387         if (argc < 3) {
388                 _E("too few argument.");
389                 return -1;
390         }
391
392         __loader_type = argv[LOADER_ARG_TYPE][0] - '0';
393         if (__loader_type < 0 || __loader_type >= LAUNCHPAD_TYPE_MAX) {
394                 _E("invalid argument. (type: %d)", __loader_type);
395                 return -1;
396         }
397
398         __loader_id = atoi(argv[LOADER_ARG_ID]);
399
400         if (callbacks == NULL) {
401                 _E("invalid argument. callback is null");
402                 return -1;
403         }
404
405         if (adapter == NULL) {
406                 _E("invalid argument. adapter is null");
407                 return -1;
408         }
409
410         if (adapter->loop_begin == NULL || adapter->loop_quit == NULL
411                 || adapter->add_fd == NULL || adapter->remove_fd == NULL) {
412                 _E("invalid argument. adapter callback is null");
413                 return -1;
414         }
415
416         __loader_callbacks = callbacks;
417         __loader_adapter = adapter;
418         __loader_user_data = user_data;
419         __argc = argc;
420         __argv = argv;
421
422         if (__before_loop(argc, argv) != 0) {
423                 _E("Failed to prepare running loader. type(%d)", __loader_type);
424                 return -1;
425         }
426
427         _D("[candidate] ecore main loop begin");
428         __loader_adapter->loop_begin(__loader_user_data);
429
430         return __after_loop();
431 }
432
433 API int launchpad_loader_set_priority(int prio)
434 {
435         return _set_priority(prio);
436 }