add exec loader
authorYoung Ik Cho <youngik.cho@samsung.com>
Wed, 21 Aug 2013 01:06:30 +0000 (10:06 +0900)
committerYoung Ik Cho <youngik.cho@samsung.com>
Wed, 21 Aug 2013 01:06:30 +0000 (10:06 +0900)
- provide different memory layout to conventional osp app

Change-Id: I0c1479bb9d3edfd319bb8d02b30be60bc2d5e4dc
Signed-off-by: Young Ik Cho <youngik.cho@samsung.com>
CMakeLists.txt
osp-exec-loader/CMakeLists.txt [new file with mode: 0644]
osp-exec-loader/exec_loader.c [new file with mode: 0644]

index 92fa1d5..f2fea44 100644 (file)
@@ -17,4 +17,5 @@ SET(EXTRA_C_FLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
 ADD_SUBDIRECTORY(osp-ui-app-loader)
 ADD_SUBDIRECTORY(osp-service-app-loader)
 ADD_SUBDIRECTORY(osp-system-service-loader)
+ADD_SUBDIRECTORY(osp-exec-loader)
 
diff --git a/osp-exec-loader/CMakeLists.txt b/osp-exec-loader/CMakeLists.txt
new file mode 100644 (file)
index 0000000..13a0278
--- /dev/null
@@ -0,0 +1,19 @@
+SET (this_target osp-exec-loader)
+
+SET (${this_target}_SOURCE_FILES
+       exec_loader.c
+       )
+
+ADD_EXECUTABLE (${this_target} ${${this_target}_SOURCE_FILES})
+
+SET(CMAKE_C_FLAGS "${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
+SET(CMAKE_CXX_FLAGS "${OSP_DEBUG_FLAGS} ${OSP_OPT_FLAGS} ${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} ${OSP_COMPILER_FLAGS}")
+
+TARGET_LINK_LIBRARIES(${this_target} "-Wl,--no-undefined -Wl,--as-needed -Wl,-Ttext-segment=0x02000000")
+TARGET_LINK_LIBRARIES(${this_target} "-ldl")
+TARGET_LINK_LIBRARIES(${this_target} ${pkgs_LDFLAGS})
+
+INSTALL(TARGETS ${this_target} DESTINATION ${LIB_INSTALL_DIR}/osp)
+
+
diff --git a/osp-exec-loader/exec_loader.c b/osp-exec-loader/exec_loader.c
new file mode 100644 (file)
index 0000000..74988dd
--- /dev/null
@@ -0,0 +1,312 @@
+//
+// 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;
+}
+