Bump up efl module version.
[platform/core/appfw/launchpad.git] / src / launchpad_common.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
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/mount.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <sys/xattr.h>
28 #include <errno.h>
29 #include <sys/socket.h>
30 #include <sys/un.h>
31 #include <linux/limits.h>
32 #include <unistd.h>
33 #include <sys/capability.h>
34 #include <tzplatform_config.h>
35 #include <stdio.h>
36 #include <stdbool.h>
37 #include <systemd/sd-journal.h>
38 #include <sys/time.h>
39 #include <sys/resource.h>
40 #include <sys/personality.h>
41 #include <glib.h>
42 #include <dbus/dbus.h>
43
44 #include "launchpad_common.h"
45 #include "key.h"
46
47 #define MAX_PATH_LEN    1024
48 #define MAX_CMD_BUFSZ 1024
49
50 #define MAX_PENDING_CONNECTIONS 10
51 #define CONNECT_RETRY_TIME (100 * 1000)
52 #define CONNECT_RETRY_COUNT 3
53 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
54 #define PATH_AMD_SOCK "/run/aul/daemons/.amd-sock"
55 #define PATH_DEV_NULL "/dev/null"
56 #define MAX_TEP_IS_MOUNT_RETRY_CNT 100
57 #define MAX_PAYLOAD_SIZE (1024 * 1024 * 1)
58
59 #define TEP_BUS_NAME                    "org.tizen.system.deviced"
60 #define TEP_OBJECT_PATH                 "/Org/Tizen/System/DeviceD/Tzip"
61 #define TEP_INTERFACE_NAME              "org.tizen.system.deviced.Tzip"
62 #define TEP_IS_MOUNTED_METHOD           "IsMounted"
63
64 #define APP2SD_BUS_NAME                 "org.tizen.app2sd"
65 #define APP2SD_OBJECT_PATH              "/org/tizen/app2sd"
66 #define APP2SD_INTERFACE_NAME           "org.tizen.app2sd"
67 #define APP2SD_ONDEMANDSETUPINIT_METHOD "OndemandSetupInit"
68 #define APP2SD_RETRY_MAX                5
69 #define APP2SD_WAIT_USEC                (1000000 / 2) /* 0.5 sec */
70
71 static int __read_proc(const char *path, char *buf, int size)
72 {
73         int fd;
74         int ret;
75
76         if (buf == NULL || path == NULL)
77                 return -1;
78
79         fd = open(path, O_RDONLY);
80         if (fd < 0)
81                 return -1;
82
83         ret = read(fd, buf, size - 1);
84         if (ret <= 0) {
85                 close(fd);
86                 return -1;
87         }
88
89         buf[ret] = 0;
90         close(fd);
91
92         return ret;
93 }
94
95 void _get_cpu_idle(unsigned long long *total, unsigned long long *idle)
96 {
97         FILE *fp;
98         int i;
99         unsigned long long sum = 0;
100         unsigned long long val;
101         unsigned long long iv = 0;
102         char buf[4] = { 0, };
103
104         fp = fopen("/proc/stat", "rt");
105
106         if (fp == NULL)
107                 return;
108
109         if (fscanf(fp, "%3s", buf) == -1) {
110                 fclose(fp);
111                 return;
112         }
113
114         for (i = 0; i < 10; i++) {
115                 if (fscanf(fp, "%lld", &val) == -1) {
116                         fclose(fp);
117                         return;
118                 }
119
120                 if (sum + val < sum) {
121                         _E("overflow");
122                         fclose(fp);
123                         return;
124                 }
125
126                 sum += val;
127                 if (i == 3) /* idle */
128                         iv = val;
129         }
130
131         fclose(fp);
132
133         *total = sum;
134         *idle = iv;
135 }
136
137 int _set_sock_option(int fd, int cli)
138 {
139         struct timeval tv = { 5, 200 * 1000 };  /*  5.2 sec */
140         int size;
141         int flag;
142         int ret;
143
144         size = AUL_SOCK_MAXBUFF;
145         ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
146         if (ret < 0) {
147                 _E("Failed to set SO_SNDBUF option on socket. errno(%d)",
148                                 errno);
149                 return -1;
150         }
151
152         ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
153         if (ret < 0) {
154                 _E("Failed to set SO_RCVBUF option on socket. errno(%d)",
155                                 errno);
156                 return -1;
157         }
158
159         if (cli) {
160                 ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
161                 if (ret < 0) {
162                         _E("Failed to set SO_RCVTIMEO option on socket. " \
163                                         "errno(%d)", errno);
164                         return -1;
165                 }
166
167                 flag = fcntl(fd, F_GETFD);
168                 flag |= FD_CLOEXEC;
169                 ret = fcntl(fd, F_SETFD, flag);
170                 if (ret < 0) {
171                         _E("Failed to manipulate fd(F_SETFD), errno(%d)",
172                                         errno);
173                         return -1;
174                 }
175         }
176
177         return 0;
178 }
179
180 static int __parse_app_path(const char *arg, char *out, int out_size)
181 {
182         register int i;
183         int state = 1;
184         char *start_out = out;
185
186         if (arg == NULL || out == NULL) {
187                 /* Handles null buffer*/
188                 return 0;
189         }
190
191         for (i = 0; out_size > 1; i++) {
192                 switch (state) {
193                 case 1:
194                         switch (arg[i]) {
195                         case ' ':
196                         case '\t':
197                                 state = 5;
198                                 break;
199                         case '\0':
200                                 state = 7;
201                                 break;
202                         case '\"':
203                                 state = 2;
204                                 break;
205                         case '\\':
206                                 state = 4;
207                                 break;
208                         default:
209                                 *out = arg[i];
210                                 out++;
211                                 out_size--;
212                                 break;
213                         }
214                         break;
215                 case 2: /* escape start*/
216                         switch (arg[i]) {
217                         case '\0':
218                                 state = 6;
219                                 break;
220                         case '\"':
221                                 state = 1;
222                                 break;
223                         default:
224                                 *out = arg[i];
225                                 out++;
226                                 out_size--;
227                                 break;
228                         }
229                         break;
230                 case 4: /* character escape*/
231                         if (arg[i] == '\0') {
232                                 state = 6;
233                         } else {
234                                 *out = arg[i];
235                                 out++;
236                                 out_size--;
237                                 state = 1;
238                         }
239                         break;
240                 case 5: /* token*/
241                         if (out != start_out) {
242                                 *out = '\0';
243                                 out_size--;
244                                 return i;
245                         }
246                         i--;
247                         state = 1;
248                         break;
249                 case 6:
250                         return -1;  /* error*/
251                 case 7: /* terminate*/
252                         *out = '\0';
253                         out_size--;
254                         return 0;
255                 default:
256                         state = 6;
257                         break;  /* error*/
258                 }
259         }
260
261         if (out_size == 1)
262                 *out = '\0';
263
264         /* Buffer overflow*/
265         return -2;
266 }
267
268 static int __create_client_socket(const char *path)
269 {
270         struct sockaddr_un addr = { 0, };
271         int retry = CONNECT_RETRY_COUNT;
272         int fd;
273
274         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
275         if (fd < 0) {
276                 _E("Failed to create socket(%s). errno(%d)", path, errno);
277                 return -1;
278         }
279
280         addr.sun_family = AF_UNIX;
281         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
282         while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
283                 if (errno != ETIMEDOUT || retry <= 0) {
284                         _E("Failed to connect socket(%s). errno(%d)",
285                                         path, errno);
286                         close(fd);
287                         return -1;
288                 }
289
290                 usleep(CONNECT_RETRY_TIME);
291                 retry--;
292                 _W("Retry(%d) to connect %s", retry, path);
293         }
294
295         return fd;
296 }
297
298 int _send_cmd_to_amd(int cmd)
299 {
300         app_pkt_t pkt = {0,};
301         int ret;
302         int fd;
303
304         fd = __create_client_socket(PATH_AMD_SOCK);
305         if (fd < 0)
306                 return -1;
307
308         pkt.cmd = cmd;
309         ret = send(fd, &pkt, sizeof(app_pkt_t), MSG_NOSIGNAL);
310         if (ret <= 0) {
311                 _E("Failed to send cmd(%d), errno(%d)", cmd, errno);
312                 close(fd);
313                 return -ECOMM;
314         }
315
316         close(fd);
317         return 0;
318 }
319
320 int _create_server_sock(const char *name)
321 {
322         struct sockaddr_un saddr;
323         int fd;
324
325         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
326         /*  support above version 2.6.27*/
327         if (fd < 0) {
328                 if (errno == EINVAL) {
329                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
330                         if (fd < 0) {
331                                 _E("second chance - socket create error");
332                                 return -1;
333                         }
334                 } else {
335                         _E("socket error");
336                         return -1;
337                 }
338         }
339
340         memset(&saddr, 0, sizeof(saddr));
341         saddr.sun_family = AF_UNIX;
342
343         snprintf(saddr.sun_path, sizeof(saddr.sun_path),
344                         "%s/daemons/%d/%s",
345                         SOCKET_PATH, getuid(), name);
346         unlink(saddr.sun_path);
347
348         if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
349                 _E("bind error");
350                 close(fd);
351                 return -1;
352         }
353
354         if (_set_sock_option(fd, 0) < 0) {
355                 _E("Failed to set sock option");
356                 close(fd);
357                 return -1;
358         }
359
360         if (listen(fd, 128) == -1) {
361                 _E("listen error");
362                 close(fd);
363                 return -1;
364         }
365
366         return fd;
367 }
368
369 app_pkt_t *_recv_pkt_raw(int fd)
370 {
371         int len;
372         int ret;
373         unsigned char buf[AUL_SOCK_MAXBUFF];
374         app_pkt_t *pkt;
375         int cmd;
376         int datalen;
377         int opt;
378
379 retry_recv:
380         /* receive header(cmd, datalen) */
381         len = recv(fd, buf, AUL_PKT_HEADER_SIZE, 0);
382         if (len < 0)
383                 if (errno == EINTR)
384                         goto retry_recv;
385
386         if (len < AUL_PKT_HEADER_SIZE) {
387                 _E("recv error");
388                 return NULL;
389         }
390         memcpy(&cmd, buf, sizeof(int));
391         memcpy(&datalen, buf + sizeof(int), sizeof(int));
392         memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
393
394         if (datalen < 0 || datalen > MAX_PAYLOAD_SIZE) {
395                 _E("Invalid protocol. datalen(%d)", datalen);
396                 return NULL;
397         }
398
399         /* allocate for a null byte */
400         pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
401         if (pkt == NULL) {
402                 _E("failed to alloc app_pkt_t");
403                 return NULL;
404         }
405         pkt->cmd = cmd;
406         pkt->len = datalen;
407         pkt->opt = opt;
408
409         len = 0;
410         while (len != pkt->len) {
411                 ret = recv(fd, pkt->data + len, pkt->len - len, 0);
412                 if (ret < 0) {
413                         _E("recv error %d %d", len, pkt->len);
414                         free(pkt);
415                         return NULL;
416                 }
417                 len += ret;
418                 _D("recv len %d %d", len, pkt->len);
419         }
420
421         return pkt;
422 }
423
424 app_pkt_t *_accept_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
425 {
426         struct sockaddr_un aul_addr = { 0, };
427         int sun_size;
428         app_pkt_t *pkt;
429         int newfd;
430         int cl = sizeof(struct ucred);
431
432         sun_size = sizeof(struct sockaddr_un);
433
434         newfd = accept(fd, (struct sockaddr *)&aul_addr,
435                         (socklen_t *) &sun_size);
436         if (newfd == -1) {
437                 if (errno != EINTR)
438                         _E("accept error");
439                 return NULL;
440         }
441
442         if (getsockopt(newfd, SOL_SOCKET, SO_PEERCRED, cr,
443                         (socklen_t *) &cl) < 0) {
444                 _E("peer information error");
445                 close(newfd);
446                 return NULL;
447         }
448
449         if (_set_sock_option(newfd, 1) < 0) {
450                 _E("Failed to set sock option");
451                 close(newfd);
452                 return NULL;
453         }
454
455         pkt = _recv_pkt_raw(newfd);
456         if (pkt == NULL) {
457                 _E("failed to receive pkt from client");
458                 close(newfd);
459                 return NULL;
460         }
461
462         *clifd = newfd;
463         return pkt;
464 }
465
466 int _send_pkt_raw(int client_fd, app_pkt_t *pkt)
467 {
468         int send_ret = 0;
469         int pkt_size = 0;
470         int sent = 0;
471
472         if (client_fd == -1 || pkt == NULL) {
473                 _E("arguments error!");
474                 return -1;
475         }
476
477         pkt_size = AUL_PKT_HEADER_SIZE + pkt->len;
478
479         while (sent != pkt_size) {
480                 send_ret = send(client_fd, (char *)pkt + sent,
481                                 pkt_size - sent, MSG_NOSIGNAL);
482                 if (send_ret == -1) {
483                         _E("send error! (%d)", errno);
484                         return -1;
485                 }
486
487                 sent += send_ret;
488                 _D("send(%d: ret: %d) : %d / %d",
489                         client_fd, send_ret, sent, pkt_size);
490         }
491
492         return 0;
493 }
494
495 appinfo_t *_appinfo_create(bundle *kb)
496 {
497         appinfo_t *menu_info;
498         const char *ptr = NULL;
499
500         menu_info = calloc(1, sizeof(appinfo_t));
501         if (menu_info == NULL)
502                 return NULL;
503
504         ptr = bundle_get_val(kb, AUL_K_APPID);
505         if (ptr)
506                 menu_info->appid = strdup(ptr);
507         ptr = bundle_get_val(kb, AUL_K_EXEC);
508         if (ptr)
509                 menu_info->app_path = strdup(ptr);
510         if (menu_info->app_path != NULL)
511                 menu_info->original_app_path = strdup(menu_info->app_path);
512         ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
513         if (ptr)
514                 menu_info->pkg_type = strdup(ptr);
515         ptr = bundle_get_val(kb, AUL_K_APP_TYPE);
516         if (ptr)
517                 menu_info->app_type = strdup(ptr);
518         ptr = bundle_get_val(kb, AUL_K_HWACC);
519         if (ptr)
520                 menu_info->hwacc = strdup(ptr);
521         ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
522         if (ptr)
523                 menu_info->taskmanage = strdup(ptr);
524         ptr = bundle_get_val(kb, AUL_K_PKGID);
525         if (ptr)
526                 menu_info->pkgid = strdup(ptr);
527         ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
528         if (ptr)
529                 menu_info->comp_type = strdup(ptr);
530         ptr = bundle_get_val(kb, AUL_K_INTERNAL_POOL);
531         if (ptr)
532                 menu_info->internal_pool = strdup(ptr);
533         ptr = bundle_get_val(kb, AUL_K_ROOT_PATH);
534         if (ptr)
535                 menu_info->root_path = strdup(ptr);
536
537         ptr = bundle_get_val(kb, AUL_K_LOADER_NAME);
538         if (ptr)
539                 menu_info->loader_name = strdup(ptr);
540
541         ptr = bundle_get_val(kb, AUL_K_IS_GLOBAL);
542         if (ptr && strcmp(ptr, "true") == 0)
543                 menu_info->global = true;
544         else
545                 menu_info->global = false;
546
547         if (!_appinfo_get_app_path(menu_info)) {
548                 _appinfo_free(menu_info);
549                 return NULL;
550         }
551
552         return menu_info;
553 }
554
555 char *_appinfo_get_app_path(appinfo_t *menu_info)
556 {
557         int i = 0;
558         int path_len = -1;
559         char *tmp_app_path;
560
561         if (!menu_info || menu_info->app_path == NULL)
562                 return NULL;
563
564         while (menu_info->app_path[i] != 0) {
565                 if (menu_info->app_path[i] == ' '
566                     || menu_info->app_path[i] == '\t') {
567                         path_len = i;
568                         break;
569                 }
570                 i++;
571         }
572
573         if (path_len == 0) {
574                 free(menu_info->app_path);
575                 menu_info->app_path = NULL;
576         } else if (path_len > 0) {
577                 tmp_app_path = malloc(sizeof(char) * (path_len + 1));
578                 if (tmp_app_path == NULL)
579                         return NULL;
580                 snprintf(tmp_app_path, path_len + 1, "%s", menu_info->app_path);
581                 free(menu_info->app_path);
582                 menu_info->app_path = tmp_app_path;
583         }
584
585         return menu_info->app_path;
586 }
587
588 void _appinfo_free(appinfo_t *menu_info)
589 {
590         if (menu_info == NULL)
591                 return;
592
593         if (menu_info->appid != NULL)
594                 free(menu_info->appid);
595         if (menu_info->app_path != NULL)
596                 free(menu_info->app_path);
597         if (menu_info->original_app_path != NULL)
598                 free(menu_info->original_app_path);
599         if (menu_info->pkg_type != NULL)
600                 free(menu_info->pkg_type);
601         if (menu_info->app_type != NULL)
602                 free(menu_info->app_type);
603         if (menu_info->hwacc != NULL)
604                 free(menu_info->hwacc);
605         if (menu_info->taskmanage != NULL)
606                 free(menu_info->taskmanage);
607         if (menu_info->pkgid != NULL)
608                 free(menu_info->pkgid);
609         if (menu_info->comp_type != NULL)
610                 free(menu_info->comp_type);
611         if (menu_info->internal_pool != NULL)
612                 free(menu_info->internal_pool);
613         if (menu_info->root_path != NULL)
614                 free(menu_info->root_path);
615         if (menu_info->loader_name != NULL)
616                 free(menu_info->loader_name);
617
618         free(menu_info);
619 }
620
621 static bool __validate_bundle_key(const char *key)
622 {
623         if (!key)
624                 return false;
625
626         if (!strncmp(key, "__AUL_", strlen("__AUL_")))
627                 return false;
628
629         if (!strncmp(key, "__APP_SVC_", strlen("__APP_SVC_")))
630                 return false;
631
632         return true;
633 }
634
635 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *menu_info, int cmd)
636 {
637         char *ptr;
638         char exe[MAX_PATH_LEN];
639         int flag;
640         char key[256];
641         char value[256];
642
643         bundle_del(kb, AUL_K_APPID);
644         bundle_del(kb, AUL_K_EXEC);
645         bundle_del(kb, AUL_K_APP_TYPE);
646         bundle_del(kb, AUL_K_PACKAGETYPE);
647         bundle_del(kb, AUL_K_TASKMANAGE);
648         bundle_del(kb, AUL_K_PKGID);
649         bundle_del(kb, AUL_K_COMP_TYPE);
650
651         /* Parse app_path to retrieve default bundle*/
652         if (cmd == PAD_CMD_LAUNCH) {
653                 ptr = menu_info->original_app_path;
654                 flag = __parse_app_path(ptr, exe, sizeof(exe));
655                 if (flag > 0) {
656                         ptr += flag;
657                         SECURE_LOGD("parsing app_path: EXEC - %s", exe);
658
659                         do {
660                                 flag = __parse_app_path(ptr, key, sizeof(key));
661                                 if (flag <= 0)
662                                         break;
663                                 ptr += flag;
664
665                                 flag = __parse_app_path(ptr, value,
666                                                 sizeof(value));
667                                 if (flag < 0)
668                                         break;
669                                 ptr += flag;
670
671                                 /*bundle_del(kb, key);*/
672                                 if (__validate_bundle_key(key))
673                                         bundle_add(kb, key, value);
674                         } while (flag > 0);
675                 } else if (flag == 0)
676                         _D("parsing app_path: No arguments");
677                 else
678                         _D("parsing app_path: Invalid argument");
679         }
680 }
681
682 int _connect_to_launchpad(int type, int id)
683 {
684         char path[PATH_MAX];
685         int client_pid;
686         int send_ret;
687         int fd;
688
689         _D("[launchpad] enter, type: %d", type);
690
691         snprintf(path, sizeof(path), "%s/daemons/%d/%s%d-%d",
692                         SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
693                         type, id);
694         fd = __create_client_socket(path);
695         if (fd < 0)
696                 return -1;
697
698         client_pid = getpid();
699         send_ret = send(fd, &client_pid, sizeof(client_pid), MSG_NOSIGNAL);
700         _D("send(%d) : %d", client_pid, send_ret);
701         if (send_ret == -1) {
702                 _E("send error");
703                 close(fd);
704                 return -1;
705         }
706
707         SECURE_LOGD("[launchpad] done, connect fd: %d", fd);
708         return fd;
709 }
710
711 #ifdef TIZEN_FEATURE_SET_PERSONALITY_32
712 static void __set_execution_domain(void)
713 {
714         char err_buf[1024];
715         int res;
716
717         res = personality(PER_LINUX32);
718         if (res < 0) {
719                 _E("personality() failed,  error: %d (%s)",
720                                 errno,
721                                 strerror_r(errno, err_buf, sizeof(err_buf)));
722         }
723 }
724 #endif /* TIZEN_FEATURE_SET_PERSONALITY_32 */
725
726 void _set_env(appinfo_t *menu_info, bundle *kb)
727 {
728         const char *str;
729         char buf[MAX_LOCAL_BUFSZ];
730
731         str = bundle_get_val(kb, AUL_K_STARTTIME);
732         if (str != NULL)
733                 setenv("APP_START_TIME", str, 1);
734
735         if (menu_info->hwacc != NULL)
736                 setenv("HWACC", menu_info->hwacc, 1);
737         if (menu_info->taskmanage != NULL)
738                 setenv("TASKMANAGE", menu_info->taskmanage, 1);
739         if (menu_info->root_path != NULL)
740                 setenv("AUL_ROOT_PATH", menu_info->root_path, 1);
741         if (menu_info->appid != NULL)
742                 setenv("AUL_APPID", menu_info->appid, 1);
743         if (menu_info->pkgid != NULL)
744                 setenv("AUL_PKGID", menu_info->pkgid, 1);
745         if (menu_info->app_type != NULL)
746                 setenv("RUNTIME_TYPE", menu_info->app_type, 1);
747
748         str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
749         if (str != NULL)
750                 setenv("WAYLAND_DISPLAY", str, 1);
751
752         str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
753         if (str != NULL)
754                 setenv("XDG_RUNTIME_DIR", str, 1);
755
756         str = bundle_get_val(kb, AUL_K_API_VERSION);
757         if (str != NULL)
758                 setenv("TIZEN_API_VERSION", str, 1);
759
760         snprintf(buf, sizeof(buf), "%d", getpid());
761         setenv("AUL_PID", buf, 1);
762
763 #ifdef TIZEN_FEATURE_SET_PERSONALITY_32
764         __set_execution_domain();
765 #endif /* TIZEN_FEATURE_SET_PERSONALITY_32 */
766 }
767
768 char **_create_argc_argv(bundle *kb, int *margc)
769 {
770         char **argv;
771         int argc;
772
773         argc = bundle_export_to_argv(kb, &argv);
774
775         *margc = argc;
776         return argv;
777 }
778
779 char *_get_libdir(const char *path)
780 {
781         char *path_dup;
782         char buf[PATH_MAX];
783         char *ptr;
784
785         if (path == NULL)
786                 return NULL;
787         path_dup = strdup(path);
788         if (path_dup == NULL)
789                 return NULL;
790         ptr = strrchr(path_dup, '/');
791         if (ptr == NULL) {
792                 free(path_dup);
793                 return NULL;
794         }
795
796         *ptr = '\0';
797
798         snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
799         free(path_dup);
800
801         if (access(buf, F_OK) == -1)
802                 return NULL;
803
804         return strdup(buf);
805 }
806
807 int _proc_get_attr_by_pid(int pid, char *buf, int size)
808 {
809         char path[PATH_MAX] = { 0, };
810         int ret;
811
812         snprintf(path, sizeof(path), "/proc/%d/attr/current", pid);
813         ret = __read_proc(path, buf, size);
814         if (ret <= 0)
815                 return -1;
816
817         return 0;
818 }
819
820 static int __delete_dir(const char *path)
821 {
822         DIR *dp;
823         struct dirent *dentry = NULL;
824         char buf[PATH_MAX];
825         struct stat statbuf;
826         int ret;
827
828         if (path == NULL)
829                 return -1;
830
831         dp = opendir(path);
832         if (dp == NULL)
833                 return -1;
834
835         while ((dentry = readdir(dp)) != NULL) {
836                 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
837                         continue;
838
839                 snprintf(buf, sizeof(buf), "%s/%s", path, dentry->d_name);
840                 ret = stat(buf, &statbuf);
841                 if (ret == 0) {
842                         if (S_ISDIR(statbuf.st_mode))
843                                 __delete_dir(buf);
844                         else
845                                 unlink(buf);
846                 }
847         }
848
849         rmdir(path);
850         closedir(dp);
851
852         return 0;
853 }
854
855 int _delete_sock_path(int pid, uid_t uid)
856 {
857         char path[PATH_MAX];
858         int r;
859
860         snprintf(path, sizeof(path), "/run/aul/apps/%d/%d", uid, pid);
861         r = access(path, F_OK);
862         if (r != 0) {
863                 if (errno != ENOENT)
864                         _E("Failed to access %s. errno(%d)", path, errno);
865         } else {
866                 __delete_dir(path);
867         }
868
869         if (access(path, F_OK) == 0) {
870                 _E("Failed to delete %s", path);
871                 return -1;
872         }
873
874         return 0;
875 }
876
877 int _close_all_fds(void)
878 {
879         DIR *dp;
880         struct dirent *dentry = NULL;
881         int fd;
882         int max_fd;
883         int aul_fd = -1;
884         const char *aul_listen_fd;
885
886         aul_listen_fd = getenv("AUL_LISTEN_FD");
887         if (aul_listen_fd)
888                 aul_fd = atoi(aul_listen_fd);
889
890         dp = opendir("/proc/self/fd");
891         if (dp == NULL) {
892                 /* fallback */
893                 max_fd = sysconf(_SC_OPEN_MAX);
894                 for (fd = 3; fd < max_fd; fd++) {
895                         if (fd != aul_fd)
896                                 close(fd);
897                 }
898
899                 return 0;
900         }
901
902         while ((dentry = readdir(dp)) != NULL) {
903                 if (!isdigit(dentry->d_name[0]))
904                         continue;
905
906                 fd = atoi(dentry->d_name);
907                 if (fd < 3)
908                         continue;
909
910                 if (fd == dirfd(dp) || fd == aul_fd)
911                         continue;
912
913                 close(fd);
914         }
915         closedir(dp);
916
917         return 0;
918 }
919
920 int _setup_stdio(const char *ident)
921 {
922         int fd;
923
924         /* stdin */
925         fd = open(PATH_DEV_NULL, O_RDONLY | O_NOCTTY);
926         if (fd < 0) {
927                 _W("Failed to open /dev/null - err(%d)", errno);
928                 return -1;
929         }
930         if (dup2(fd, STDIN_FILENO) < 0) {
931                 _W("Failed to duplicate fd - oldfd(%d), newfd(%d)",
932                                 fd, STDIN_FILENO);
933         }
934         close(fd);
935
936         /* stdout */
937         fd = sd_journal_stream_fd(ident, LOG_INFO, false);
938         if (fd < 0) {
939                 _W("Failed to connect journal socket - err(%d)", errno);
940                 fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY);
941                 if (fd < 0) {
942                         _W("Failed to open /dev/null - err(%d)", errno);
943                         return -1;
944                 }
945         }
946         if (dup2(fd, STDOUT_FILENO) < 0) {
947                 _W("Failed to duplicate fd - oldfd(%d), newfd(%d)",
948                                 fd, STDOUT_FILENO);
949         }
950         close(fd);
951
952         /* stderr */
953         fd = sd_journal_stream_fd(ident, LOG_INFO, false);
954         if (fd < 0) {
955                 _W("Failed to connect journal socket - err(%d)", errno);
956                 fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY);
957                 if (fd < 0) {
958                         _W("Failed to open /dev/null - err(%d)", errno);
959                         return -1;
960                 }
961         }
962         if (dup2(fd, STDERR_FILENO) < 0) {
963                 _W("Failed to duplicate fd - oldfd(%d), newfd(%d)",
964                                 fd, STDERR_FILENO);
965         }
966         close(fd);
967
968         return 0;
969 }
970
971 int _set_priority(int prio)
972 {
973         int r;
974
975         r = setpriority(PRIO_PGRP, 0, prio);
976         if (r < 0) {
977                 SECURE_LOGE("Failed to set process(%d) priority(%d) - err(%d)",
978                                 getpid(), prio, errno);
979         }
980
981         return r;
982 }
983
984 static int __dbus_send_message(DBusMessage *callback(void *), void *user_data,
985                 int timeout, int *result)
986 {
987         DBusError err;
988         DBusConnection *conn;
989         DBusMessage *msg = NULL;
990         DBusMessageIter args;
991         DBusPendingCall *pending = NULL;
992         dbus_bool_t r;
993         dbus_int32_t i;
994         int ret = 0;
995
996         dbus_error_init(&err);
997         conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
998         if (!conn) {
999                 _E("Failed to connect to D-Bus Daemon");
1000                 ret = -1;
1001                 goto end;
1002         }
1003
1004         msg = callback(user_data);
1005         if (!msg) {
1006                 _E("Message is nullptr");
1007                 goto end;
1008         }
1009
1010         r = dbus_connection_send_with_reply(conn, msg, &pending, timeout);
1011         if (!r || !pending) {
1012                 _E("Failed to send message");
1013                 ret = -1;
1014                 goto end;
1015         }
1016
1017         dbus_connection_flush(conn);
1018         dbus_message_unref(msg);
1019
1020         dbus_pending_call_block(pending);
1021         msg = dbus_pending_call_steal_reply(pending);
1022         if (!msg) {
1023                 _E("Failed to get reply message");
1024                 ret = -1;
1025                 goto end;
1026         }
1027
1028         dbus_pending_call_unref(pending);
1029
1030         if (!dbus_message_iter_init(msg, &args)) {
1031                 _E("Message has no arguments!");
1032                 ret = -1;
1033         } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_INT32) {
1034                 _E("Argument is not integer! type(%d)",
1035                                 dbus_message_iter_get_arg_type(&args));
1036                 ret = -1;
1037         } else {
1038                 dbus_message_iter_get_basic(&args, &i);
1039                 *result = i;
1040         }
1041
1042         _D("Result: %d", *result);
1043 end:
1044         if (msg)
1045                 dbus_message_unref(msg);
1046
1047         if (conn)
1048                 dbus_connection_close(conn);
1049
1050         if (dbus_error_is_set(&err)) {
1051                 _E("D-Bus error(%s)", err.message);
1052                 dbus_error_free(&err);
1053         }
1054
1055         return ret;
1056 }
1057
1058 static DBusMessage *__create_tep_mount_message(void *user_data)
1059 {
1060         DBusMessage *message;
1061         DBusMessageIter args;
1062         dbus_bool_t r;
1063         const char *tep_path = (const char *)user_data;
1064
1065         message = dbus_message_new_method_call(TEP_BUS_NAME,
1066                         TEP_OBJECT_PATH,
1067                         TEP_INTERFACE_NAME,
1068                         TEP_IS_MOUNTED_METHOD);
1069         if (!message) {
1070                 _E("Message is nullptr");
1071                 return NULL;
1072         }
1073
1074         dbus_message_iter_init_append(message, &args);
1075         r = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &tep_path);
1076         if (!r) {
1077                 _E("Out of memory");
1078                 dbus_message_unref(message);
1079                 return NULL;
1080         }
1081
1082         return message;
1083 }
1084
1085 static int __is_tep_mount_done(const char *tep_path)
1086 {
1087         int result = -1;
1088         int ret;
1089
1090         ret = __dbus_send_message(__create_tep_mount_message,
1091                         (void *)tep_path, 500, &result);
1092         if (ret != 0)
1093                 _E("Failed to send message");
1094
1095         return result;
1096 }
1097
1098 static int __check_tep_mount(const char *tep_path)
1099 {
1100         int r;
1101         int cnt = 0;
1102
1103         if (!tep_path)
1104                 return 0;
1105
1106         while (cnt < MAX_TEP_IS_MOUNT_RETRY_CNT) {
1107                 r = __is_tep_mount_done(tep_path);
1108                 if (r == 1)
1109                         break;
1110                 usleep(50 * 1000);
1111                 cnt++;
1112         }
1113
1114         if (r != 1) {
1115                 _E("Not able to mount within 5 sec: %s", tep_path);
1116                 return -1;
1117         }
1118
1119         return 0;
1120 }
1121
1122 int _wait_tep_mount(bundle *b)
1123 {
1124         int r;
1125         int i;
1126         int len = 0;
1127         const char **tep_paths;
1128
1129         tep_paths = bundle_get_str_array(b, AUL_K_TEP_PATH, &len);
1130         if (!tep_paths)
1131                 return 0;
1132
1133         for (i = 0; i < len; ++i) {
1134                 r = __check_tep_mount(tep_paths[i]);
1135                 if (r < 0)
1136                         return -1;
1137         }
1138
1139         _I("Mount has been done.");
1140         return 0;
1141 }
1142
1143 static int __create_app_socket(int pid, uid_t uid)
1144 {
1145         int fd;
1146         char path[PATH_MAX];
1147         struct sockaddr_un addr = {
1148                 .sun_family = AF_UNIX,
1149         };
1150
1151         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
1152         if (fd < 0) {
1153                 if (errno == EINVAL) {
1154                         fd = socket(AF_UNIX, SOCK_STREAM, 0);
1155                         if (fd < 0) {
1156                                 _E("Second chance - socket create errno(%d)",
1157                                                 errno);
1158                                 return -1;
1159                         }
1160                 } else {
1161                         _E("Failed to create socket. errno(%d)", errno);
1162                         return -1;
1163                 }
1164         }
1165
1166         snprintf(path, sizeof(path), "/run/aul/apps/%u/%d", uid, pid);
1167         if (mkdir(path, 0700) != 0) {
1168                 if (errno == EEXIST) {
1169                         if (access(path, R_OK) != 0) {
1170                                 _E("Failed to access %s. errno(%d)",
1171                                                 path, errno);
1172                                 close(fd);
1173                                 return -errno;
1174                         }
1175                 } else {
1176                         _E("Failed to access %s. errno(%d)", path, errno);
1177                         close(fd);
1178                         return -1;
1179                 }
1180         }
1181
1182         snprintf(addr.sun_path, sizeof(addr.sun_path),
1183                         "/run/aul/apps/%u/%d/.app-sock", uid, pid);
1184         unlink(addr.sun_path);
1185
1186         if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
1187                 _E("Failed to bind socket(%d), errno(%d)", fd, errno);
1188                 close(fd);
1189                 return -1;
1190         }
1191
1192         if (_set_sock_option(fd, 0) < 0) {
1193                 _E("Failed to set sock option");
1194                 close(fd);
1195                 return -1;
1196         }
1197
1198         if (listen(fd, 128) < 0) {
1199                 _E("Failed to listen %d, errno(%d)", fd, errno);
1200                 close(fd);
1201                 return -1;
1202         }
1203
1204         return fd;
1205 }
1206
1207 int _prepare_app_socket(void)
1208 {
1209         int fd;
1210         char buf[12];
1211
1212         fd = __create_app_socket(getpid(), getuid());
1213         if (fd < 0)
1214                 return fd;
1215
1216         snprintf(buf, sizeof(buf), "%d", fd);
1217         setenv("AUL_LISTEN_FD", buf, 1);
1218
1219         return 0;
1220 }
1221
1222 struct package_info_s {
1223         const char *id;
1224         uid_t uid;
1225 };
1226
1227 static DBusMessage *__create_app2sd_message(void *user_data)
1228 {
1229         struct package_info_s *pkg_info = (struct package_info_s *)user_data;
1230         DBusMessage *message;
1231         DBusMessageIter args;
1232         dbus_bool_t r;
1233
1234         _D("[__APP2SD__] package(%s), uid(%u)", pkg_info->id, pkg_info->uid);
1235
1236         message = dbus_message_new_method_call(APP2SD_BUS_NAME,
1237                         APP2SD_OBJECT_PATH,
1238                         APP2SD_INTERFACE_NAME,
1239                         APP2SD_ONDEMANDSETUPINIT_METHOD);
1240         if (!message) {
1241                 _E("Message is nullptr");
1242                 return NULL;
1243         }
1244
1245         dbus_message_iter_init_append(message, &args);
1246         r = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,
1247                         &pkg_info->id);
1248         if (!r) {
1249                 _E("Failed to append pkgid");
1250                 dbus_message_unref(message);
1251                 return NULL;
1252         }
1253
1254         r = dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32,
1255                         &pkg_info->uid);
1256         if (!r) {
1257                 _E("Failed to append uid");
1258                 dbus_message_unref(message);
1259                 return NULL;
1260         }
1261
1262         return message;
1263 }
1264
1265 int _enable_external_pkg(bundle *b, const char *pkgid, uid_t pkg_uid)
1266 {
1267         const char *installed_storage;
1268         int retry_cnt = 0;
1269         int result = -1;
1270         int ret;
1271         struct package_info_s pkg_info = {
1272                 .id = pkgid,
1273                 .uid = pkg_uid
1274         };
1275
1276         installed_storage = bundle_get_val(b, AUL_K_INSTALLED_STORAGE);
1277         if (!installed_storage || strcmp(installed_storage, "external") != 0)
1278                 return 0;
1279
1280         do {
1281                 ret = __dbus_send_message(__create_app2sd_message,
1282                                 &pkg_info, 500, &result);
1283                 if (ret != 0) {
1284                         _E("Failed to send message");
1285                         retry_cnt++;
1286                         usleep(APP2SD_WAIT_USEC);
1287                         continue;
1288                 }
1289
1290                 break;
1291         } while (retry_cnt <= APP2SD_RETRY_MAX);
1292
1293         _D("[__APP2SD__] result(%d)", result);
1294
1295         return result;
1296 }
1297
1298 int _verify_proc_caps(void)
1299 {
1300         cap_t cap_d;
1301         cap_flag_value_t eff_state;
1302         cap_flag_value_t inh_state;
1303         cap_value_t value = CAP_SETGID;
1304         int r;
1305
1306         cap_d = cap_get_proc();
1307         if (!cap_d) {
1308                 _E("Failed to get cap from proc. pid(%d)", getpid());
1309                 return -1;
1310         }
1311
1312         r = cap_get_flag(cap_d, value, CAP_INHERITABLE, &inh_state);
1313         if (r != 0) {
1314                 _E("Failed to get cap inh - errno(%d)", errno);
1315                 cap_free(cap_d);
1316                 return -1;
1317         }
1318
1319         r = cap_get_flag(cap_d, value, CAP_EFFECTIVE, &eff_state);
1320         if (r != 0) {
1321                 _E("Failed to get cap eff - errno(%d)", errno);
1322                 cap_free(cap_d);
1323                 return -1;
1324         }
1325
1326         if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) {
1327                 _E("The process(%d) doesn't have %d cap",
1328                                 getpid(), value);
1329                 cap_free(cap_d);
1330                 return -1;
1331         }
1332         cap_free(cap_d);
1333
1334         return 0;
1335 }
1336
1337 int _prepare_id_file(void)
1338 {
1339         char path[PATH_MAX];
1340         int fd;
1341
1342         snprintf(path, sizeof(path), "/run/aul/apps/%u/%d/%s",
1343                         getuid(), getpid(), getenv("AUL_APPID"));
1344         fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0600);
1345         if (fd < 0) {
1346                 _E("Failed to create %s. errno(%d)", path, errno);
1347                 return -1;
1348         }
1349         close(fd);
1350
1351         return 0;
1352 }
1353
1354 static int __send_raw(int fd, int cmd, unsigned char *data, int datalen)
1355 {
1356         app_pkt_t *pkt;
1357         int ret;
1358
1359         pkt = (app_pkt_t *)calloc(1, sizeof(app_pkt_t) + datalen);
1360         if (!pkt) {
1361                 _E("Out of memory");
1362                 return -ENOMEM;
1363         }
1364
1365         pkt->cmd = cmd;
1366         pkt->len = datalen;
1367         if (data)
1368                 memcpy(pkt->data, data, pkt->len);
1369
1370         ret = _send_pkt_raw(fd, pkt);
1371         if (ret < 0) {
1372                 free(pkt);
1373                 return -1;
1374         }
1375
1376         free(pkt);
1377
1378         return 0;
1379 }
1380
1381 int _send_message_to_logger(const char *tag, const char *format, ...)
1382 {
1383         char fmt[PATH_MAX];
1384         char buf[PATH_MAX];
1385         va_list ap;
1386         int ret;
1387         int fd;
1388
1389         snprintf(buf, sizeof(buf), "%s/daemons/%u/.launchpad-logger-sock",
1390                         SOCKET_PATH, getuid());
1391         fd = __create_client_socket(buf);
1392         if (fd < 0)
1393                 return -1;
1394
1395         va_start(ap, format);
1396         vsnprintf(fmt, sizeof(fmt), format, ap);
1397         va_end(ap);
1398
1399         snprintf(buf, sizeof(buf), "%s: %s", tag, fmt);
1400         ret = __send_raw(fd, 0, (unsigned char *)buf, strlen(buf) + 1);
1401         if (ret < 0) {
1402                 close(fd);
1403                 return -1;
1404         }
1405
1406         close(fd);
1407
1408         return 0;
1409 }