BuildRequires: cmake
BuildRequires: gettext
BuildRequires: edje-tools
-BuildRequires: pkgconfig(ail)
+BuildRequires: libcap-devel
BuildRequires: pkgconfig(aul)
+BuildRequires: pkgconfig(ail)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(ewebkit2)
BuildRequires: pkgconfig(appcore-efl)
${TARGET_CORE_MODULE_LIB}
${SMACK_LABELING_SUPPORT_STATIC}
${PROF_LIB}
+ "-lcap"
"-pie"
)
destroyAppInfoHandle(handle);
return true;
}
+
+std::string SecuritySupport::getPluginProcessSoftLinkPath(const std::string& tzAppId)
+{
+ const std::string npruntimePostfix = ".npruntime";
+
+ ail_appinfo_h handle = NULL;
+ std::string appBinPath;
+
+ Try
+ {
+ getAppInfo(tzAppId, &handle);
+ char* path = getExePath(handle);
+ appBinPath = path;
+ }
+ Catch(Exception::Base)
+ {
+ destroyAppInfoHandle(handle);
+ return "";
+ }
+
+ destroyAppInfoHandle(handle);
+ return appBinPath + npruntimePostfix;
+}
} // ClientModule
namespace ClientModule {
namespace SecuritySupport {
bool setAppPrivilege(const std::string& tizenAppId);
+std::string getPluginProcessSoftLinkPath(const std::string& tzAppId);
} // namespace SecuritySupport
} // namespace ClientModule
#endif // CLIENT_SECURITY_SUPPORT_H_
\ No newline at end of file
std::string tizenId =
ClientModule::CommandLineParser::getTizenId(argc, argv);
+
+ // CapabilitySupport
+ std::string pluginProcessPath =
+ ClientModule::SecuritySupport::getPluginProcessSoftLinkPath(tizenId);
+ setenv("PLUGIN_PROCESS_EXECUTABLE_PATH_FOR_PROCESS_POOL",
+ pluginProcessPath.c_str(), 1);
+ LogDebug("PLUGIN_PROCESS_EXECUTABLE_PATH_FOR_PROCESS_POOL = " <<
+ pluginProcessPath);
+
ewk_context_message_post_to_injected_bundle(
s_preparedEwkContext,
MESSAGE_NAME_INITIALIZE,
appcore_set_i18n("wrt-client", NULL);
ewk_set_arguments(argc, argv);
setenv("WRT_LAUNCHING_PERFORMANCE", "1", 1);
+
+ // CapabilitySupport
+ std::string pluginProcessPath =
+ ClientModule::SecuritySupport::getPluginProcessSoftLinkPath(tizenId);
+ setenv("PLUGIN_PROCESS_EXECUTABLE_PATH",
+ pluginProcessPath.c_str(), 1);
+ LogDebug("PLUGIN_PROCESS_EXECUTABLE_PATH = " <<
+ pluginProcessPath);
+
s_preparedEwkContext = ewk_context_new_with_injected_bundle_path(
BUNDLE_PATH);
TARGET_LINK_LIBRARIES( ${WRT_LAUNCH_PAD_NAME}
${WRT_LAUNCH_PAD_DEPS_LIBRARIES}
${CMAKE_DL_LIBS}
+ "-lcap"
)
#install
--- /dev/null
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 execute_on_whole_thread_util.h
+ * @author Tae-Jeong Lee (taejeong.lee@samsung.com)
+ * @version 1.0
+ */
+
+#ifndef __EXECUTE_ON_WHOLE_THREAD_UTIL_H__
+#define __EXECUTE_ON_WHOLE_THREAD_UTIL_H__
+
+#include <assert.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/syscall.h>
+
+// define
+#define _EXEC_FILE_MAX_LEN 1024
+#define _EXEC_MAX_RETRY_CNT 1000
+
+// typedef
+typedef void (*exec_func_t)();
+
+// static variable
+static exec_func_t _s_exec_func = NULL;
+static sighandler_t _s_prev_handler = NULL;
+static int _s_exec_waiting_task_cnt = 0;
+
+// internal function
+static void _exec_signal_handler(int signum)
+{
+ (void) signum;
+
+ if (_s_exec_func)
+ {
+ _s_exec_func();
+ }
+
+ _s_exec_waiting_task_cnt--;
+}
+
+static int _set_exec_signal_handler(int signum)
+{
+ sighandler_t ret;
+
+ ret = signal(signum, _exec_signal_handler);
+
+ if (ret == SIG_ERR)
+ {
+ return -1;
+ }
+ else
+ {
+ _s_prev_handler = ret;
+ }
+
+ return 0;
+}
+
+static int _restore_signal_handler(int signum)
+{
+ if (_s_prev_handler)
+ {
+ if (signal(signum, _s_prev_handler) == SIG_ERR)
+ {
+ return -1;
+ }
+
+ _s_prev_handler = NULL;
+ }
+ else
+ {
+ if (signal(signum, SIG_DFL) == SIG_ERR)
+ {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int _send_signal_to_whole_thread(int signum)
+{
+ int ret;
+ DIR *dir;
+ struct dirent entry, *result;
+ char proc_self_task_path[_EXEC_FILE_MAX_LEN + 1] = {0, };
+
+ sprintf(proc_self_task_path, "/proc/self/task");
+
+ dir = opendir(proc_self_task_path);
+
+ if (dir)
+ {
+ for (ret = readdir_r(dir, &entry, &result);
+ result != NULL && ret == 0;
+ ret = readdir_r(dir, &entry, &result))
+ {
+ if (strncmp(entry.d_name, ".", 2) == 0 ||
+ strncmp(entry.d_name, "..", 3) == 0)
+ {
+ continue;
+ }
+
+ _s_exec_waiting_task_cnt++;
+ if (syscall(__NR_tkill, atoi(entry.d_name), signum) != 0)
+ {
+ // syscall failed
+ _s_exec_waiting_task_cnt--;
+ }
+ }
+
+ closedir(dir);
+ }
+ else
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _is_main_thread()
+{
+ int pid = getpid();
+ int tid = syscall(__NR_gettid);
+
+ return (pid == tid);
+}
+
+static int _waiting_for_done()
+{
+ int i;
+
+ for (i=0; _s_exec_waiting_task_cnt && i < _EXEC_MAX_RETRY_CNT; i++)
+ {
+ usleep(100); // 0.1ms
+ }
+
+ if (i == _EXEC_MAX_RETRY_CNT)
+ {
+ // time over
+ return -1;
+ }
+
+ return 0;
+}
+
+// external API
+int EXECUTE_ON_WHOLE_THREAD(exec_func_t exec_func, int using_signum)
+{
+ int signum;
+
+ assert(_s_exec_waiting_task_cnt == 0 && exec_func != NULL);
+ assert(using_signum == SIGUSR1 || using_signum == SIGUSR2);
+
+ // check main thread
+ if (!_is_main_thread())
+ {
+ return -1;
+ }
+
+ signum = using_signum;
+ _s_exec_func = exec_func;
+
+ // set signal handler
+ if (_set_exec_signal_handler(signum) != 0)
+ {
+ goto onerr_EXECUTE_ON_WHOLE_THREAD;
+ }
+
+ // send signal
+ if (_send_signal_to_whole_thread(signum) != 0)
+ {
+ goto onerr_EXECUTE_ON_WHOLE_THREAD;
+ }
+
+ // waiting
+ if (_waiting_for_done() != 0)
+ {
+ goto onerr_EXECUTE_ON_WHOLE_THREAD;
+ }
+
+ // restore signal handler to previous
+ _restore_signal_handler(signum);
+ _s_exec_waiting_task_cnt = 0;
+ _s_exec_func = NULL;
+ _s_prev_handler = NULL;
+
+ return 0;
+
+
+onerr_EXECUTE_ON_WHOLE_THREAD:
+ _restore_signal_handler(signum);
+ _s_exec_waiting_task_cnt = 0;
+ _s_exec_func = NULL;
+ _s_prev_handler = NULL;
+
+ return -1;
+}
+
+#endif // __EXECUTE_ON_WHOLE_THREAD_UTIL_H__
#include <aul.h>
#include <bundle.h>
+#include <errno.h>
#include <privilege-control.h>
#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <unistd.h>
#include "config.h"
#include "gl.h"
_static_ void __modify_bundle(bundle * kb, int caller_pid, app_info_from_db * menu_info, int cmd);
_static_ void __set_oom();
_static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
+_static_ void __set_inherit_bit_for_CAP_MAC_ADMIN();
// Implementation
_static_ char** __create_argc_argv(bundle * kb, int *margc)
}
}
+_static_ void __set_inherit_bit_for_CAP_MAC_ADMIN()
+{
+ cap_t caps = NULL;
+ cap_value_t target_caps[] = { CAP_MAC_ADMIN };
+
+ caps = cap_init();
+
+ if (caps == NULL) {
+ goto err_set_inherit_bit_for_CAP_MAC_ADMIN;
+ }
+
+ if (cap_set_flag(caps, CAP_INHERITABLE,
+ sizeof(target_caps)/sizeof(cap_value_t),
+ target_caps, CAP_SET)) {
+ _E("cap_set_flag() failed!! : %s", strerror(errno));
+ goto err_set_inherit_bit_for_CAP_MAC_ADMIN;
+ }
+
+ if (cap_set_proc(caps)) {
+ _E("cap_set_proc() failed!! : %s", strerror(errno));
+ goto err_set_inherit_bit_for_CAP_MAC_ADMIN;
+ }
+
+ if (cap_free(caps)) {
+ _E("cap_free() failed!!");
+ }
+
+ return;
+
+err_set_inherit_bit_for_CAP_MAC_ADMIN:
+ if (caps != NULL) {
+ cap_free(caps);
+ }
+
+ return;
+}
+
#endif // __LAUNCHPAD_UTIL_H_
#include <stdlib.h>
#include <launchpad_util.h>
#include <smack_labeling_support.h>
+#include <execute_on_whole_thread_util.h>
// Prototype
_static_ int __process_pool_prepare_exec(const char *pkg_name, const char *app_path, app_info_from_db * menu_info, bundle * kb);
return -1;
}
+ /* SET INHERIT BIT FOR CAP_MAC_ADMIN TO WHOLE THREAD */
+ EXECUTE_ON_WHOLE_THREAD(__set_inherit_bit_for_CAP_MAC_ADMIN, SIGUSR1);
+
/* SET PROCESS NAME*/
if (app_path == NULL) {
_D("app_path should not be NULL - check menu db");
memset(pkg_id, '\0', PKG_ID_LENGTH);
snprintf(pkg_id, PKG_ID_LENGTH, "%s", pkg_name);
+ /* SET PR_SET_KEEPCAPS */
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ _E("prctl(PR_SET_KEEPCAPS) failed.");
+ }
+
if (__set_access(pkg_id, menu_info->pkg_type, app_path) < 0) {
_D("fail to set privileges - check your package's credential\n");
return -1;
}
+ __set_inherit_bit_for_CAP_MAC_ADMIN();
+
/* SET DUMPABLE - for coredump*/
prctl(PR_SET_DUMPABLE, 1);
__signal_unset_sigchld();
__signal_fini();
+ /* SET PR_SET_KEEPCAPS */
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ _E("prctl(PR_SET_KEEPCAPS) failed.");
+ }
+
/* SET DUMPABLE - for coredump*/
prctl(PR_SET_DUMPABLE, 1);