--- /dev/null
+//
+// Open Service Platform
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file exec_loader.c
+* @brief This is the implementation for the osp-exec-loader.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <linux/capability.h>
+
+#include <dlog.h>
+#include <appinfo.h>
+
+#undef LOG_TAG
+#define LOG_TAG "LOADER"
+
+#define MAX_PACKAGEID 10
+#define MAX_APP_EXECUTABLE_NAME 230
+#define MAX_APPID (MAX_PACKAGEID + MAX_APP_EXECUTABLE_NAME + 1)
+
+
+static const char APPFW_SONAME[] = "libosp-appfw.so.1";
+
+
+#if 0
+static void
+print_args(int argc, char* argv[])
+{
+ const char* p = NULL;
+ int i = 0;
+ for (; i < argc; i++)
+ {
+ p = argv[i];
+ LOGD("%dth arg : [%s]", i, p);
+ }
+}
+#endif
+
+static void
+adjust_privilege(const char* appid)
+{
+ void* handle = dlopen("libprivilege-control.so.0", RTLD_LAZY | RTLD_LOCAL);
+ if (!handle)
+ {
+ fprintf(stderr, "Cannot open libprivilege-control.so.0\n");
+ return;
+ }
+
+ char* msg = 0;
+ dlerror();
+
+ int (*ppriv_func)(const char*) = NULL;
+
+ ppriv_func = (int (*)(const char*))dlsym(handle, "set_privilege");
+ msg = dlerror();
+ if (msg != NULL)
+ {
+ fprintf(stderr, "Dlsym error: %s\n", msg);
+
+ dlclose(handle);
+ return;
+ }
+
+ int ret = (*ppriv_func)(appid);
+ if (ret < 0)
+ {
+ fprintf(stderr, "set_privilege() returned %d\n", ret);
+ }
+
+ dlclose(handle);
+}
+
+extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
+
+static int
+adjust_capability(void)
+{
+ cap_user_header_t head = 0;
+ cap_user_data_t data = 0;
+
+ head = (cap_user_header_t) malloc(sizeof(*head));
+ if (head == NULL)
+ {
+ fprintf(stderr, "Memory allocation failure.\n");
+ return -1;
+ }
+
+ head->version = _LINUX_CAPABILITY_VERSION;
+ head->pid = getpid();
+
+ data = (cap_user_data_t) calloc(sizeof(*data), _LINUX_CAPABILITY_U32S);
+ if (data == NULL)
+ {
+ fprintf(stderr, "Memory allocation failure.\n");
+
+ free(head);
+ return -1;
+ }
+
+ data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
+ data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
+
+ if (capset(head, data) < 0)
+ {
+ fprintf(stderr, "Capability setting error\n");
+
+ free(data);
+ free(head);
+ return -1;
+ }
+
+ free(data);
+ free(head);
+
+ return 0;
+}
+
+static int
+osp_do_pre_exe(const char* bin_path)
+{
+ int ret = 0;
+ void* handle = NULL;
+ char* errormsg = 0;
+ int (*do_pre_exec_fn)(const char*, const char*) = NULL;
+
+ handle = dlopen("libosp-env-config.so", RTLD_LAZY | RTLD_LOCAL);
+ if (!handle)
+ {
+ LOGE("Failed to dlopen osp-env-config.so (%s)", dlerror());
+ return -1;
+ }
+ LOGD("dlopen() ok");
+
+ do_pre_exec_fn = (int (*)(const char*, const char*)) dlsym(handle, "do_pre_exec");
+ errormsg = dlerror();
+ if (errormsg != NULL)
+ {
+ LOGE("Failed to dlsym() (%s)", errormsg);
+ dlclose(handle);
+ return -1;
+ }
+ LOGD("dlsym() ok");
+
+ ret = do_pre_exec_fn(NULL, bin_path);
+ if (ret < 0)
+ {
+ LOGE("Failed to do_pre_exe() (%d)", ret);
+ }
+ LOGD("do_pre_exec() ok");
+
+ dlclose(handle);
+
+ return 0;
+}
+
+static int
+get_packageid_executable_name_from_path(const char path[], char packageid[], char executable_name[])
+{
+ // path is ".../[packageid]/bin/[executable_name]"
+
+ const char* p = strrchr(path, '/');
+ if (p == NULL)
+ {
+ LOGI("Improper path %s", path);
+ return -1;
+ }
+
+ const int path_len = strlen(path);
+ const int exec_len = strlen(p);
+ if (exec_len <= 0 || exec_len > PATH_MAX || path_len <= 0 || path_len > PATH_MAX)
+ {
+ LOGI("Improper path %s", path);
+ return -1;
+ }
+
+ strncpy(executable_name, p + 1, exec_len);
+
+#ifdef _SECURE_LOG
+ LOGI("Exec is %s", executable_name);
+#endif
+
+ if (path_len < /* '/' */ 1 + 10 + strlen("/bin/") + exec_len)
+ {
+ LOGI("Improper path %s", path);
+ return -1;
+ }
+
+ strncpy(packageid, p - strlen("bin/") - 10, 10);
+
+ LOGI("PackageId is %s", packageid);
+
+ return 1;
+}
+
+
+int
+main(int argc, char* argv[])
+{
+ void* handle = NULL;
+ char* errormsg = 0;
+ char packageid[MAX_PACKAGEID + 1];
+ char executable_name[MAX_APP_EXECUTABLE_NAME];
+ char appid[MAX_APPID];
+
+ void (*pAppInfoInit)(const char*, const char*, int, char* [], int) = NULL;
+ int (*pRealMain)(int, char* []) = NULL;
+
+ memset(packageid, 0, sizeof(packageid));
+ memset(executable_name, 0, sizeof(executable_name));
+ memset(appid, 0, sizeof(appid));
+
+ LOGI("Initializeing : argc %d, argv 0x%x.", argc, argv);
+ //print_args(argc, argv);
+
+ // convert package path to package name
+ get_packageid_executable_name_from_path(argv[0], packageid, executable_name);
+ snprintf(appid, MAX_APPID, "%s.%s", packageid, executable_name);
+
+#ifdef _SECURE_LOG
+ LOGI("app is %s", appid);
+#endif
+
+ if (getuid() == 0)
+ {
+ // self caging
+ osp_do_pre_exe(argv[0]);
+
+ // adjust privilege
+ adjust_privilege(appid);
+ }
+
+
+ adjust_capability();
+
+ // initialize appid
+ appinfo_init(appid, 0);
+ appinfo_set_argv(argc, argv);
+
+ // actual loading
+ char buffer[1024];
+
+ snprintf(buffer, 1024, "%s.exe", argv[0]);
+
+
+ void* so_handle = dlopen(APPFW_SONAME, RTLD_LAZY);
+ if (!so_handle)
+ {
+ LOGE("Failed to open framework : %s.", dlerror());
+ return -1;
+ }
+
+ pAppInfoInit = (void (*)(const char*, const char*, int, char*[], int)) dlsym(so_handle, "InitAppInfo");
+ errormsg = dlerror();
+ if (errormsg != NULL)
+ {
+ LOGE("Failed to find InitAppInfo() : %s.", errormsg);
+ fprintf(stderr, "Improper osp library entry : %s.\n", errormsg);
+ dlclose(so_handle);
+ return -1;
+ }
+
+ handle = dlopen(buffer, RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle)
+ {
+ LOGE("Failed to open %s : %s.", buffer, dlerror());
+ dlclose(so_handle);
+ return -1;
+ }
+
+ pRealMain = (int (*)(int, char*[])) dlsym(handle, "OspMain");
+ errormsg = dlerror();
+ if (errormsg != NULL)
+ {
+ LOGE("Failed to find OspMain() : %s.", errormsg);
+ dlclose(handle);
+ dlclose(so_handle);
+ return -1;
+ }
+
+ // actual initialization
+ (*pAppInfoInit)(packageid, executable_name, argc, argv, -1);
+ (*pRealMain)(argc, argv);
+
+ LOGI("Osp application terminates.");
+
+ dlclose(handle);
+ LOGI("Osp cleanup finished for %s.", argv[0]);
+
+ return 0;
+}
+