7c0ea3fed6f4468b57d177640a5c2ae60f468b93
[platform/framework/native/env-config.git] / src / osp-env-config.c
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #ifndef _GNU_SOURCE
19 #define _GNU_SOURCE
20 #endif
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sched.h>
26 #include <sys/mount.h>
27 #include <errno.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <limits.h>
31 #include <sys/prctl.h>
32 #include <sys/vfs.h>
33 #include <fcntl.h>
34 #include <dlfcn.h>
35
36 #include <dlog.h>
37 #include <vconf.h>
38 #include <appinfo.h>
39
40 #undef LOG_TAG
41 #define LOG_TAG "ENV_CONFIG"
42
43 #define _MAX_PACKAGEID_LENGTH 10
44 #define _MAX_APIVERSION_LENGTH 3
45
46 #ifdef _SECURE_LOG
47 #define _SECURE_LOGI LOGI
48 #define _SECURE_LOGE LOGE
49 #else
50 #define _SECURE_LOGI(...)
51 #define _SECURE_LOGE(...)
52 #endif
53
54 static const char _OSP_COMPAT_SHARED_PATH[] = "/opt/usr/share/.osp-compat/\0";
55 static const char _EXT_OSP_HOME_PATH[] = "/opt/storage/sdcard/osp/\0";
56 static const char OSP_COMPAT_LIB[] = "/usr/lib/osp/libosp-compat.so";
57
58 struct _path_info
59 {
60         char src_path[PATH_MAX];
61         const char dest_path[PATH_MAX];
62 };
63
64 struct _dir_info
65 {
66         char path[PATH_MAX];
67         mode_t mode;
68         char app_privilege; // 0: root privilege
69 };
70
71 /*
72  * XXX: The returned app_roodir must be freed in caller.
73  */
74 static char*
75 get_app_rootpath_from_path(const char* bin_path)
76 {
77         char* app_rootpath = NULL;
78         char* delimiter = NULL;
79         size_t length = 0;
80
81         /* e.g., The specified bin_path is "/opt/apps/com.samsung.basicapp/bin/basicapp" */
82         length = strlen(bin_path);
83         app_rootpath = (char *)malloc(length + 1);
84         if(app_rootpath == NULL)
85                 return NULL;
86
87         memset(app_rootpath, '\0', length + 1);
88         strncpy(app_rootpath, bin_path, length);
89
90         _SECURE_LOGI("input bin_path: %s", app_rootpath);
91
92         delimiter = strrchr(app_rootpath, '/');
93         *delimiter = '\0';
94
95         delimiter  = strrchr(app_rootpath, '/');
96         *delimiter = '\0';
97
98         return app_rootpath;
99 }
100
101
102 static int
103 internal_is_mounted(const char* pkgid)
104 {
105         char mount_flag[64] = { 0, };
106         static const char dir[][64] =
107         {
108                 { "/tmp/osp-compat" },
109                 { "/tmp/osp-compat/mount" },
110                 { "/tmp/osp-compat/mount/internal" }
111         };
112
113         sprintf(mount_flag, "/tmp/osp-compat/mount/internal/%s", pkgid);
114         int res = access(mount_flag, F_OK);
115         if (res == 0)
116         {
117                 LOGI("Intenal path is already mounted.");
118                 return 1;
119         }
120         else if (res == -1 && errno == ENOENT)
121         {
122                 int i = 0;
123                 for (i = 0; i < sizeof(dir)/64; ++i)
124                 {
125                         int res = mkdir(dir[i], 0755);
126                         if (res == -1 && errno != EEXIST)
127                         {
128                                 LOGE("Failed to create directory (%s), errno: %d (%s)", dir[i], errno, strerror(errno));
129                                 return 1;
130                         }
131                 }
132
133                 int fd = creat(mount_flag, 0644);
134                 if (fd == -1)
135                 {
136                         LOGE("Failed to create mount flag (%s), errno: %d (%s)", mount_flag, errno, strerror(errno));
137                         return 1;
138                 }
139                 close(fd);
140         }
141         else
142         {
143                 LOGE("Failed to access mount flag (%s), errno: %d (%s)", mount_flag, errno, strerror(errno));
144                 return 1;
145         }
146
147         LOGI("Intenal path mount succeeded.");
148         return 0;
149 }
150
151 static int
152 external_is_mounted(const char* pkgid)
153 {
154         char mount_flag[64] = { 0, };
155         static const char dir[][64] =
156         {
157                 { "/tmp/osp-compat" },
158                 { "/tmp/osp-compat/mount" },
159                 { "/tmp/osp-compat/mount/external" }
160         };
161
162         sprintf(mount_flag, "/tmp/osp-compat/mount/external/%s", pkgid);
163         int res = access(mount_flag, F_OK);
164         if (res == 0)
165         {
166                 LOGI("Extenal path is already mounted.");
167                 return 1;
168         }
169         else if (res == -1 && errno == ENOENT)
170         {
171                 int i = 0;
172                 for (i = 0; i < sizeof(dir)/64; ++i)
173                 {
174                         int res = mkdir(dir[i], 0755);
175                         if (res == -1 && errno != EEXIST)
176                         {
177                                 LOGE("Failed to create directory (%s), errno: %d (%s)", dir[i], errno, strerror(errno));
178                                 return 1;
179                         }
180                 }
181
182                 int fd = creat(mount_flag, 0644);
183                 if (fd == -1)
184                 {
185                         LOGE("Failed to create mount flag (%s), errno: %d (%s)", mount_flag, errno, strerror(errno));
186                         return 1;
187                 }
188                 close(fd);
189         }
190         else
191         {
192                 LOGE("Failed to access mount flag (%s), errno: %d (%s)", mount_flag, errno, strerror(errno));
193                 return 1;
194         }
195
196         LOGI("Extenal path mount succeeded.");
197         return 0;
198 }
199
200 static int
201 mount_native_paths(const char* app_rootpath)
202 {
203         int i = 0;
204         static const struct _path_info mount_info[] =
205         {
206                 //{ "/bin",                             "./bin" },
207                 { "/csa",                               "./csa" },
208                 { "/dev",                               "./dev" },
209                 { "/dev/pts",                   "./dev/pts" },
210                 { "/dev/shm",                   "./dev/shm" },
211                 { "/etc",                               "./etc" },
212                 { "/lib",                               "./lib" },
213                 { "/mnt",                               "./mnt" },
214                 { "/proc",                              "./proc" },
215                 { "/sbin",                              "./sbin" },
216                 { "/smack",                             "./smack" },
217                 { "/srv",                               "./srv" },
218                 { "/sys",                               "./sys" },
219                 { "/sys/kernel/debug",  "./sys/kernel/debug" },
220                 { "/tmp",                               "./tmp" },
221                 { "/usr",                               "./usr" },
222                 { "/var",                               "./var" },
223                 { "/var/run",                   "./var/run" },
224                 { "/opt",                               "./opt" },
225                 { "/opt/usr",                   "./opt/usr" },
226                 { "/opt/var/kdb/db",    "./opt/var/kdb/db" },
227                 //{ "/opt/storage/sdcard","./opt/storage/sdcard" }
228         };
229
230         if (chdir(app_rootpath) != 0)
231         {
232                 LOGE("chdir() failed path: %s, errno: %d (%s)", app_rootpath, errno, strerror(errno));
233                 return -1;
234         }
235
236         for (i = 0; i < sizeof(mount_info)/sizeof(struct _path_info); ++i)
237         {
238                 if (mount(mount_info[i].src_path, mount_info[i].dest_path, NULL, MS_BIND, NULL) != 0)
239                 {
240                         LOGE("mount() failed, src path: %s, dest path: %s, errno: %d (%s)",
241                                         mount_info[i].src_path, mount_info[i].dest_path, errno, strerror(errno));
242
243                         int j = 0;
244                         for (j = i; j > 0; --j)
245                         {
246                                 umount2(mount_info[j-1].dest_path, MNT_DETACH);
247                         }
248                         return -1;
249                 }
250         }
251
252         return 0;
253 }
254
255 static int
256 mount_osp_internal_paths(const char* app_rootpath, const char* pkgid)
257 {
258         int i = 0;
259         char osp_share_pkgid_path[PATH_MAX] = {0, };
260         char osp_share2_pkgid_path[PATH_MAX] = {0, };
261         struct _path_info mount_info[] =
262         {
263                 { "\0", "./data/Share" },
264                 { "\0", "./data/Share2" },
265                 { "/opt/usr/share/.osp-compat/share",   "./Share" },
266                 { "/opt/usr/share/.osp-compat/share2",  "./Share2" },
267                 { "/opt/usr/media",                     "./Media" }
268         };
269
270         strncpy(osp_share_pkgid_path, _OSP_COMPAT_SHARED_PATH, strlen(_OSP_COMPAT_SHARED_PATH));
271         strncat(osp_share_pkgid_path, "share/", 6);
272         strncat(osp_share_pkgid_path, pkgid, strlen(pkgid));
273
274         strncpy(osp_share2_pkgid_path, _OSP_COMPAT_SHARED_PATH, strlen(_OSP_COMPAT_SHARED_PATH));
275         strncat(osp_share2_pkgid_path, "share2/", 7);
276         strncat(osp_share2_pkgid_path, pkgid, strlen(pkgid));
277
278         strncpy(mount_info[0].src_path, osp_share_pkgid_path, strlen(osp_share_pkgid_path));
279         strncpy(mount_info[1].src_path, osp_share2_pkgid_path, strlen(osp_share2_pkgid_path));
280
281         if (chdir(app_rootpath) != 0)
282         {
283                 LOGE("chdir() failed, path: %s, errno: %d (%s)", app_rootpath, errno, strerror(errno));
284                 return -1;
285         }
286
287         for (i = 0; i < sizeof(mount_info)/sizeof(struct _path_info); ++i)
288         {
289                 if (mount(mount_info[i].src_path, mount_info[i].dest_path, NULL, MS_BIND, NULL) != 0)
290                 {
291                         LOGE("mount() failed, src path: %s, dest path: %s, errno: %d (%s)",
292                                         mount_info[i].src_path, mount_info[i].dest_path, errno, strerror(errno));
293
294                         int j = 0;
295                         for (j = i; j > 0; --j)
296                         {
297                                 umount2(mount_info[j-1].dest_path, MNT_DETACH);
298                         }
299                         return -1;
300                 }
301         }
302
303         return 0;
304 }
305
306 static int
307 mount_linux_paths(const char* app_rootpath)
308 {
309         int i = 0;
310         static const struct _path_info mount_info[] =
311         {
312                 { "/bin",                               "./bin" },
313                 { "/cache",                             "./cache" },
314                 { "/csa",                               "./csa" },
315                 { "/data",                              "./data" },
316                 { "/dev",                               "./dev" },
317                 { "/dev/pts",                   "./dev/pts" },
318                 { "/dev/shm",                   "./dev/shm" },
319                 { "/etc",                               "./etc" },
320                 { "/lib",                               "./lib" },
321                 { "/lib/modules",               "./lib/modules" },
322                 { "/media",                             "./media" },
323                 { "/mnt",                               "./mnt" },
324                 { "/proc",                              "./proc" },
325                 { "/run",                               "./run" },
326                 { "/sbin",                              "./sbin" },
327                 { "/smack",                             "./smack" },
328                 { "/srv",                               "./srv" },
329                 { "/sys",                               "./sys" },
330                 { "/sys/fs/cgroup",             "./sys/fs/cgroup" },
331                 { "/sys/fs/cgroup/systemd",     "./sys/fs/cgroup/systemd" },
332                 { "/system",                    "./system" },
333                 { "/tmp",                               "./tmp" },
334                 { "/usr",                               "./usr" },
335                 { "/var",                               "./var" },
336                 { "/var/run",                   "./var/run" },
337                 { "/opt",                               "./opt" },
338                 { "/opt/usr",                   "./opt/usr" },
339                 //{ "/opt/var/run",             "./opt/var/run" },
340                 { "/opt/storage/sdcard","./opt/storage/sdcard" },
341         };
342
343         if (chdir(app_rootpath) != 0)
344         {
345                 LOGE("chdir() failed path: %s, errno: %d (%s)", app_rootpath, errno, strerror(errno));
346                 return -1;
347         }
348
349         for (i = 0; i < sizeof(mount_info)/sizeof(struct _path_info); ++i)
350         {
351                 if (i == 27) // /opt/storage/sdcard
352                 {
353                         int mmc_mounted = 0;
354                         int ret = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmc_mounted);
355                         if (ret < 0)
356                         {
357                                 LOGE("vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS) failed.");
358                         }
359                         if (mmc_mounted == 0)
360                         {
361                                 continue;
362                         }
363                 }
364
365                 LOGI("src path: %s, dest path: %s", mount_info[i].src_path, mount_info[i].dest_path);
366                 if (mount(mount_info[i].src_path, mount_info[i].dest_path, NULL, MS_BIND, NULL) != 0)
367                 {
368                         LOGE("mount() failed, src path: %s, dest path: %s, errno: %d (%s)",
369                                         mount_info[i].src_path, mount_info[i].dest_path, errno, strerror(errno));
370
371                         int j = 0;
372                         for (j = i; j > 0; --j)
373                         {
374                                 umount2(mount_info[j-1].dest_path, MNT_DETACH);
375                         }
376                         return -1;
377                 }
378         }
379
380         return 0;
381 }
382
383 static int
384 create_osp_external_paths(const char* app_rootpath, const char* pkgid)
385 {
386         char osp_ext_apps_pkgid_path[PATH_MAX] = {0, };
387         char osp_ext_apps_pkgid_share_path[PATH_MAX] = {0, };
388         char osp_ext_apps_pkgid_share2_path[PATH_MAX] = {0, };
389         char osp_ext_share_pkgid_path[PATH_MAX] = {0, };
390         char osp_ext_share2_pkgid_path[PATH_MAX] = {0, };
391         struct _dir_info external_dirs[] =
392         {
393                 { "./HomeExt",          0000,   0 },
394                 { "./ShareExt",         0000,   0 },
395                 { "./Share2Ext",        0000,   0 },
396                 { "/opt/storage/sdcard/osp",            0777,   0 },
397                 { "/opt/storage/sdcard/osp/apps",       0777,   0 },
398                 { "/opt/storage/sdcard/osp/share",      0777,   0 },
399                 { "/opt/storage/sdcard/osp/share2",     0777,   0 },
400                 { "\0", 0777,   0},
401                 { "\0", 0777,   0},
402                 { "\0", 0777,   0},
403                 { "\0", 0777,   0},
404                 { "\0", 0777,   0},
405                 { "/opt/storage/sdcard/Images", 0777,   0 },
406                 { "/opt/storage/sdcard/Sounds", 0777,   0 },
407                 { "/opt/storage/sdcard/Videos", 0777,   0 },
408                 { "/opt/storage/sdcard/Others", 0777,   0 }
409         };
410         int i = 0;
411
412         strncpy(osp_ext_apps_pkgid_path, _EXT_OSP_HOME_PATH, strlen(_EXT_OSP_HOME_PATH));
413         strncat(osp_ext_apps_pkgid_path, "apps/", 5);
414         strncat(osp_ext_apps_pkgid_path, pkgid, strlen(pkgid));
415
416         strncpy(osp_ext_apps_pkgid_share_path, osp_ext_apps_pkgid_path, strlen(osp_ext_apps_pkgid_path));
417         strncat(osp_ext_apps_pkgid_share_path, "/Share", 6);
418
419         strncpy(osp_ext_apps_pkgid_share2_path, osp_ext_apps_pkgid_path, strlen(osp_ext_apps_pkgid_path));
420         strncat(osp_ext_apps_pkgid_share2_path, "/Share2", 7);
421
422         strncpy(osp_ext_share_pkgid_path, _EXT_OSP_HOME_PATH, strlen(_EXT_OSP_HOME_PATH));
423         strncat(osp_ext_share_pkgid_path, "share/", 6);
424         strncat(osp_ext_share_pkgid_path, pkgid, strlen(pkgid));
425
426         strncpy(osp_ext_share2_pkgid_path, _EXT_OSP_HOME_PATH, strlen(_EXT_OSP_HOME_PATH));
427         strncat(osp_ext_share2_pkgid_path, "share2/", 7);
428         strncat(osp_ext_share2_pkgid_path, pkgid, strlen(pkgid));
429
430         strncpy(external_dirs[7].path, osp_ext_apps_pkgid_path, strlen(osp_ext_apps_pkgid_path));
431         strncpy(external_dirs[8].path, osp_ext_apps_pkgid_share_path, strlen(osp_ext_apps_pkgid_share_path));
432         strncpy(external_dirs[9].path, osp_ext_apps_pkgid_share2_path, strlen(osp_ext_apps_pkgid_share2_path));
433         strncpy(external_dirs[10].path, osp_ext_share_pkgid_path, strlen(osp_ext_share_pkgid_path));
434         strncpy(external_dirs[11].path, osp_ext_share2_pkgid_path, strlen(osp_ext_share2_pkgid_path));
435
436         if (chdir(app_rootpath) != 0)
437         {
438                 LOGE("chdir() failed (%s), path: %s", strerror(errno), app_rootpath);
439                 return -1;
440         }
441
442         for (i = 0; i < sizeof(external_dirs)/sizeof(struct _dir_info); i++)
443         {
444                 int ret = mkdir(external_dirs[i].path, external_dirs[i].mode);
445                 if (ret == -1 && errno != 17) // EEXIST
446                 {
447                         LOGE("mkdir() failed, path: %s, errno: %d (%s)", external_dirs[i].path, errno, strerror(errno));
448                         return -1;
449                 }
450         }
451
452         return 0;
453 }
454
455 static int
456 mount_osp_external_paths(const char* app_rootpath, const char* pkgid)
457 {
458         char osp_ext_apps_pkgid_path[PATH_MAX] = {0, };
459         char osp_ext_share_pkgid_path[PATH_MAX] = {0, };
460         char osp_ext_share2_pkgid_path[PATH_MAX] = {0, };
461         struct _path_info mount_info[] =
462         {
463                 { "/opt/storage/sdcard",                        "./Storagecard/Media"   },
464                 { "/opt/storage/sdcard/osp/share",      "./ShareExt"                    },
465                 { "/opt/storage/sdcard/osp/share2",     "./Share2Ext"                   },
466                 { "\0", "./HomeExt"                     },
467                 { "\0", "./HomeExt/Share"       },
468                 { "\0", "./HomeExt/Share2"      }
469         };
470         int i = 0;
471
472         strncpy(osp_ext_apps_pkgid_path, _EXT_OSP_HOME_PATH, strlen(_EXT_OSP_HOME_PATH));
473         strncat(osp_ext_apps_pkgid_path, "apps/", 5);
474         strncat(osp_ext_apps_pkgid_path, pkgid, strlen(pkgid));
475
476         strncpy(osp_ext_share_pkgid_path, _EXT_OSP_HOME_PATH, strlen(_EXT_OSP_HOME_PATH));
477         strncat(osp_ext_share_pkgid_path, "share/", 6);
478         strncat(osp_ext_share_pkgid_path, pkgid, strlen(pkgid));
479
480         strncpy(osp_ext_share2_pkgid_path, _EXT_OSP_HOME_PATH, strlen(_EXT_OSP_HOME_PATH));
481         strncat(osp_ext_share2_pkgid_path, "share2/", 7);
482         strncat(osp_ext_share2_pkgid_path, pkgid, strlen(pkgid));
483
484         strncpy(mount_info[3].src_path, osp_ext_apps_pkgid_path, strlen(osp_ext_apps_pkgid_path));
485         strncpy(mount_info[4].src_path, osp_ext_share_pkgid_path, strlen(osp_ext_share_pkgid_path));
486         strncpy(mount_info[5].src_path, osp_ext_share2_pkgid_path, strlen(osp_ext_share2_pkgid_path));
487
488         if (chdir(app_rootpath) != 0)
489         {
490                 LOGE("chdir() failed, path: %s, errno: %d (%s)", app_rootpath, errno, strerror(errno));
491                 return -1;
492         }
493         LOGI("app_rootpath: %s", app_rootpath);
494
495         for (i = 0; i < sizeof(mount_info)/sizeof(struct _path_info); i++)
496         {
497                 if (mount(mount_info[i].src_path, mount_info[i].dest_path, NULL, MS_BIND, NULL) != 0)
498                 {
499                         LOGE("mount() failed, src path: %s, dest path: %s, errno: %d (%s)",
500                                         mount_info[i].src_path, mount_info[i].dest_path, errno, strerror(errno));
501
502                         int j = 0;
503                         for (j = i; j > 0; --j)
504                         {
505                                 umount2(mount_info[j-1].dest_path, MNT_DETACH);
506                         }
507                         return -1;
508                 }
509         }
510
511         return 0;
512 }
513
514 int
515 do_pre_exe(const char* bin_path, const char* package_id)
516 {
517         char* app_rootpath = NULL;
518         int mmc_mounted = 0;
519
520         // preload libosp-compat.so.1 for compatibility
521         void* handle = dlopen(OSP_COMPAT_LIB, RTLD_GLOBAL);
522         if (handle)
523         {
524                 LOGI("%s is preloaded.", OSP_COMPAT_LIB);
525         }
526
527         /* e.g., app_rootdir is "/opt/usr/apps/[pkgId] */
528         app_rootpath = get_app_rootpath_from_path(bin_path);
529
530         _SECURE_LOGI("[data_caging] do_pre_exe() was called, package id: %s, binary path: %s, app root: %s",
531                         package_id, bin_path, app_rootpath);
532
533         umask(0000);
534
535         if (!internal_is_mounted(package_id))
536         {
537                 if (mount_native_paths(app_rootpath) != 0)
538                 {
539                         goto ERROR;
540                 }
541                 if (mount_osp_internal_paths(app_rootpath, package_id) != 0)
542                 {
543                         goto ERROR;
544                 }
545         }
546
547         int ret = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &mmc_mounted);
548         if (ret < 0)
549         {
550                 LOGE("vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS) failed.");
551         }
552         if (mmc_mounted == 1)
553         {
554                 LOGI("MMC is mounted.");
555                 if (create_osp_external_paths(app_rootpath, package_id) != 0)
556                 {
557                         goto ERROR;
558                 }
559
560                 if (!external_is_mounted(package_id))
561                 {
562                         if (mount_osp_external_paths(app_rootpath, package_id) != 0)
563                         {
564                                 goto ERROR;
565                         }
566                 }
567         }
568         LOGI("mount() succeeded.");
569
570         if (chroot(app_rootpath) != 0)
571         {
572                 LOGE("chroot() failed, path: %s, errno: %d (%s)", app_rootpath, errno, strerror(errno));
573                 goto ERROR;
574         }
575         if (chdir("/") != 0)
576         {
577                 LOGE("chdir() failed, path: /, errno: %d (%s)", errno, strerror(errno));
578                 goto ERROR;
579         }
580         LOGI("chroot() succeeded.");
581
582         if (chdir("/data") != 0)
583         {
584                 LOGE("chdir() failed, path: /data, errno: %d (%s)", errno, strerror(errno));
585                 goto ERROR;
586         }
587
588         free(app_rootpath);
589         umask(0022);
590
591         LOGI("[data_caging] do_pre_exe() succeeded.");
592         return 0;
593
594 ERROR:
595         free(app_rootpath);
596         umask(0022);
597
598         LOGI("[data_caging] do_pre_exe() failed.");
599         return -1;
600 }
601
602 static int
603 do_virtual_root(const char* virtual_root_path, const char* package_id)
604 {
605         _SECURE_LOGI("[virtual_root] do_virtual_root() was called, virtual root path: %s, package id: %s",
606                         virtual_root_path, package_id);
607
608         umask(0000);
609
610         if (!internal_is_mounted(package_id))
611         {
612                 if (mount_linux_paths(virtual_root_path) != 0)
613                 {
614                         goto ERROR;
615                 }
616         }
617         LOGI("mount() succeeded.");
618
619         if (chroot(virtual_root_path) != 0)
620         {
621                 LOGE("chroot() failed. path: %s, errno: %d (%s)", virtual_root_path, errno, strerror(errno));
622                 goto ERROR;
623         }
624         if (chdir("/") != 0)
625         {
626                 LOGE("chdir() failed. path: /data, errno: %d (%s)", errno, strerror(errno));
627                 goto ERROR;
628         }
629         LOGI("chroot() succeeded.");
630
631         umask(0022);
632
633         LOGI("[virtual_root] do_virtual_root() succeeded.");
634         return 0;
635
636 ERROR:
637         umask(0022);
638
639         LOGI("[virtual_root] do_virtual_root() failed.");
640         return -1;
641 }
642
643 int
644 do_pre_exec(const char* package_name, const char* bin_path)
645 {
646         char* app_rootpath = NULL;
647         char app_compat_path[PATH_MAX] = { 0, };
648         const char app_compat_file[] = "/info/compat.info\0";
649         char osp_app_data_path[PATH_MAX] = { 0, };
650         int osp_compat = 0;
651
652         _SECURE_LOGI("do_pre_exec() is called, app name: %s, binary path: %s", package_name, bin_path);
653
654         app_rootpath = get_app_rootpath_from_path(bin_path);
655
656         strncpy(app_compat_path, app_rootpath, strlen(app_rootpath));
657         strncat(app_compat_path, app_compat_file, strlen(app_compat_file));
658         if (access(app_compat_path, F_OK) == 0)
659         {
660                 osp_compat = 1;
661         }
662
663         appinfo_init(package_name, 0);
664         appinfo_set_compat(osp_compat);
665
666         const char* package_id = appinfo_get_packageid();
667
668         _SECURE_LOGI("package id: %s, binary path: %s, OSP compat: %d", package_id, bin_path, osp_compat);
669
670         // FIXME: Temporary code with security risk
671         prctl(PR_SET_KEEPCAPS, 1);
672
673         if (osp_compat == 1)
674         {
675                 free(app_rootpath);
676                 //unshare(CLONE_NEWNS);
677                 return do_pre_exe(bin_path, package_id);
678         }
679
680         char virtual_root_file[PATH_MAX] = { 0, };
681         const char virtual_root_info[] = "/info/virtualroot.info";
682         strncpy(virtual_root_file, app_rootpath, strlen(app_rootpath));
683         strncat(virtual_root_file, virtual_root_info, strlen(virtual_root_info));
684         if (access(virtual_root_file, F_OK) == 0)
685         {
686                 LOGI("This is virtual root application.");
687                 int fd = open(virtual_root_file, O_RDONLY);
688                 if (fd < 0)
689                 {
690                         LOGE("failed to open %s, errno: %d (%s)", virtual_root_file, errno, strerror(errno));
691                         goto ERROR;
692                 }
693
694                 char user_path[PATH_MAX] = { 0, };
695                 int read_bytes = read(fd, user_path, PATH_MAX);
696                 if (read_bytes < 0)
697                 {
698                         LOGE("failed to read %s, errno: %d (%s)", virtual_root_file, errno, strerror(errno));
699                         close(fd);
700                         goto ERROR;
701                 }
702                 close(fd);
703
704                 char virtual_root_path[PATH_MAX] = { 0, };
705                 sprintf(virtual_root_path, "%s/data/%s", app_rootpath, user_path);
706
707                 int res = do_virtual_root(virtual_root_path, package_id);
708                 free(app_rootpath);
709                 return res;
710         }
711
712         // API version is equal to or greater than Tizen 2.0
713         // Set current working dir to "/opt/apps/{pkgId}/data"
714         strncpy(osp_app_data_path, app_rootpath, strlen(app_rootpath));
715         strncat(osp_app_data_path, "/data", strlen("/data"));
716
717         if (chdir(osp_app_data_path) != 0)
718         {
719                 LOGE("chdir() failed, path: %s, errno: %d (%s)", osp_app_data_path, errno, strerror(errno));
720                 goto ERROR;
721         }
722
723         LOGI("[data_caging] do_pre_exec() succeeded.");
724         free(app_rootpath);
725         return 0;
726
727 ERROR:
728         free(app_rootpath);
729         return -1;
730 }
731