#include <tzplatform_config.h>
#include <pthread.h>
#include <dlfcn.h>
+#include <sys/smack.h>
#include "sysdeps.h"
#include "log.h"
#define PROC_CMDLINE_PATH "/proc/cmdline"
#define USB_SERIAL_PATH "/sys/class/usb_mode/usb0/iSerial"
+#define APPID2PID_PATH "/usr/bin/appid2pid"
#include <sys/ioctl.h>
#include <net/if.h>
#endif
int HOST = 0;
+
+// sdk user
uid_t g_sdk_user_id;
gid_t g_sdk_group_id;
char* g_sdk_home_dir = NULL;
int rootshell_mode; // 0: sdk user, 1: root
int booting_done; // 0: platform booting is in progess 1: platform booting is done
+// root user
+uid_t g_root_user_id;
+gid_t g_root_group_id;
+char* g_root_home_dir = NULL;
+char* g_root_home_dir_env = NULL;
+
struct group_info
{
const char *name;
{"log", -1},
{NULL, -1}
};
+
#define SDB_DEFAULT_GROUPS_CNT ((sizeof(g_default_groups)/sizeof(g_default_groups[0]))-1)
int is_init_sdk_userinfo = 0;
#endif
}
+int is_appid2pid_supported(void) {
+
+ if (access(APPID2PID_PATH, F_OK) == 0) {
+ /* It is necessary to confirm that it is possible
+ * to run "appid2pid" in the sdk user/group privileges. */
+ struct stat st;
+ if (stat(APPID2PID_PATH, &st) == 0) {
+ D("appid2pid uid=%d, gid=%d, mode=0x%x.\n", st.st_uid, st.st_gid, st.st_mode);
+ if ( (st.st_uid == STATIC_SDK_USER_ID && st.st_mode & S_IXUSR)
+ || (st.st_gid == STATIC_SDK_GROUP_ID && st.st_mode & S_IXGRP)
+ || (st.st_mode & S_IXOTH) ) {
+ D("appid2pid is supported.\n");
+ return 1;
+ }
+ }
+ } else {
+ D("failed to access appid2pid file: %d\n", errno);
+ }
+
+ D("appid2pid is NOT supported.\n");
+ return 0;
+}
+
int is_container_enabled(void) {
bool value;
int ret;
#endif
#ifdef SUPPORT_ENCRYPT
-/*
+/*
desc. : 암호화 실패 메시지 전송
parameter : [in] apacket* p : sdbd로 들어온 메시지
[in] atransport *t : 현재 연결에 대한 atransport
//put_apacket(enc_p);
}
-/*
+/*
desc. : 암호화 메시지 핸들링
parameter : [in] apacket* p : sdbd로 들어온 메시지
[in/out] atransport *t : 현재 연결에 대한 atransport
if(p->msg.arg0 == ENCR_SET_ON_REQ){ // hello 메시지인 경우
t->sessionID = sessionID;
- if((retVal = security_init(t->sessionID, NULL)) == 1){ // 암호화 handshaking을 위한 init
+ if((retVal = security_init(t->sessionID, NULL)) == 1){ // 암호화 handshaking을 위한 init
if(security_parse_server_hello(t->sessionID, p) == 1){ // hello 메시지 파싱
D("security_parse_server_hello success\n");
enc_p = get_apacket();
if(security_gen_client_hello(t->sessionID, enc_p) == 1){ // hello 메시지 생성
- D("security_gen_client_hello success\n");
+ D("security_gen_client_hello success\n");
enc_p->msg.command = A_ENCR;
enc_p->msg.arg0 = ENCR_SET_ON_REQ;
enc_p->msg.arg1 = p->msg.arg1;
D("security_gen_client_hello error\n");
send_encr_fail(p, t, ENCR_ON_FAIL); // 암호화 on 실패 메시지 전송
t->encryption = ENCR_OFF; // 암호화 모드는 off
- security_deinit(t->sessionID);
+ security_deinit(t->sessionID);
return -1;
}
}
send_encr_fail(p, t, ENCR_ON_FAIL);
t->encryption = ENCR_OFF;
security_deinit(t->sessionID);
-
+
return -1;
}
} else { // init 실패
}
//put_apacket(enc_p);
return 0;
-
+
}
#endif
}
}
-static int sdbd_set_groups() {
+static int sdbd_set_groups(const char *name, int gid, struct group_info default_groups[], int default_groups_size) {
gid_t *group_ids = NULL;
int ngroups = 0;
int i, j = 0;
int group_match = 0;
int added_group_cnt = 0;
- getgrouplist(SDK_USER_NAME, g_sdk_group_id, NULL, &ngroups);
+ getgrouplist(name, gid, NULL, &ngroups);
D("group list : ngroups = %d\n", ngroups);
- group_ids = malloc((ngroups + SDB_DEFAULT_GROUPS_CNT) * sizeof(gid_t));
+ group_ids = malloc((ngroups + default_groups_size) * sizeof(gid_t));
if (group_ids == NULL) {
- D("failed to allocate group_ids(%d)\n", (ngroups + SDB_DEFAULT_GROUPS_CNT) * sizeof(gid_t));
+ D("failed to allocate group_ids(%d)\n", (ngroups + default_groups_size) * sizeof(gid_t));
return -1;
}
- if (getgrouplist(SDK_USER_NAME, g_sdk_group_id, group_ids, &ngroups) == -1) {
+ if (getgrouplist(name, gid, group_ids, &ngroups) == -1) {
D("failed to getgrouplist(), ngroups = %d\n", ngroups);
free(group_ids);
return -1;
}
-
- for (i = 0; g_default_groups[i].name != NULL; i++) {
- for (j = 0; j < ngroups; j++) {
- if (group_ids[j] == g_default_groups[i].gid) {
- group_match = 1;
- break;
+ if(default_groups_size >= 1) {
+ for (i = 0; default_groups[i].name != NULL; i++) {
+ for (j = 0; j < ngroups; j++) {
+ if (group_ids[j] == default_groups[i].gid) {
+ group_match = 1;
+ break;
+ }
}
+ if (group_match == 0 && default_groups[i].gid != -1) {
+ group_ids[ngroups + added_group_cnt] = default_groups[i].gid;
+ added_group_cnt ++;
+ }
+ group_match = 0;
}
- if (group_match == 0 && g_default_groups[i].gid != -1) {
- group_ids[ngroups + added_group_cnt] = g_default_groups[i].gid;
- added_group_cnt ++;
- }
- group_match = 0;
}
-
if (setgroups(ngroups+added_group_cnt, group_ids) != 0) {
D("failed to setgroups().\n");
free(group_ids);
return 0;
}
-int set_sdk_user_privileges() {
+int set_sdk_user_privileges(int is_drop_capability_after_fork) {
if (!is_init_sdk_userinfo) {
D("failed to init sdk user information.\n");
return -1;
}
- if (sdbd_set_groups() < 0) {
+ /*
+ * If a process switches its real, effective, or saved uids from at least one being 0 to all being non-zero,
+ * then both the permitted and effective capabilities are cleared.
+ */
+ if(is_drop_capability_after_fork) {
+
+ if (setuid(g_root_user_id) != 0) {
+ D("set root user id failed (errno: %d)\n", errno);
+ return -1;
+ }
+ }
+
+ if (sdbd_set_groups(SDK_USER_NAME, g_sdk_group_id, g_default_groups, SDB_DEFAULT_GROUPS_CNT) < 0) {
D("set groups failed (errno: %d)\n", errno);
return -1;
}
if (setuid(g_sdk_user_id) != 0) {
D("set user id failed (errno: %d)\n", errno);
return -1;
+// if(is_drop_capability_after_fork) {
+// return -1;
+// }
}
if (chdir(g_sdk_home_dir) < 0) {
return 0;
}
+int set_root_privileges() {
+
+ if (sdbd_set_groups(ROOT_USER_NAME, g_root_group_id, NULL, 0) < 0) {
+ D("set root groups failed (errno: %d)\n", errno);
+ }
+
+ if (setgid(g_root_group_id) != 0) {
+ D("set root group id failed (errno: %d)\n", errno);
+ }
+
+ if (setuid(g_root_user_id) != 0) {
+ D("set root user id failed (errno: %d)\n", errno);
+ }
+
+ if (chdir(g_root_home_dir) < 0) {
+ D("unable to change root working directory to %s\n", g_sdk_home_dir);
+ }
+
+ // TODO: use pam later
+ if (g_root_home_dir_env) {
+ putenv(g_root_home_dir_env);
+ }
+
+ return 0;
+}
+
#define SDB_PW_GR_DEFAULT_SIZE (16*1024)
static long get_passwd_bufsize() {
long bufsize = 0;
return 0;
}
-static void set_static_userinfo() {
+static void set_static_root_userinfo() {
+ g_root_user_id = STATIC_ROOT_USER_ID;
+ g_root_group_id = STATIC_ROOT_GROUP_ID;
+ g_root_home_dir = STATIC_ROOT_HOME_DIR;
+}
+
+static void set_static_sdk_userinfo() {
g_sdk_user_id = STATIC_SDK_USER_ID;
g_sdk_group_id = STATIC_SDK_GROUP_ID;
g_sdk_home_dir = STATIC_SDK_HOME_DIR;
}
+static int init_root_userinfo() {
+ struct passwd pwd;
+ char *buf = NULL;
+ long bufsize = 0;
+
+ bufsize = get_passwd_bufsize();
+ buf = malloc(bufsize);
+ if (buf == NULL) {
+ D("failed to allocate passwd buf(%ld)\n", bufsize);
+ set_static_root_userinfo();
+ } else {
+ if (sdbd_get_user_pwd(ROOT_USER_NAME, &pwd, buf, bufsize) < 0) {
+ D("failed to get root user passwd info.(errno: %d)\n", errno);
+ set_static_root_userinfo();
+ } else {
+ D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
+
+ g_root_user_id = pwd.pw_uid;
+ g_root_group_id = pwd.pw_gid;
+ g_root_home_dir = strdup(pwd.pw_dir);
+ }
+ free(buf);
+ }
+
+ int env_size = strlen("HOME=") + strlen(g_root_home_dir) + 1;
+ g_root_home_dir_env = malloc(env_size);
+ if(g_root_home_dir_env == NULL) {
+ D("failed to allocate for home dir env string\n");
+ } else {
+ snprintf(g_root_home_dir_env, env_size, "HOME=%s", g_root_home_dir);
+ }
+
+ return 0;
+}
+
static int init_sdk_userinfo() {
struct passwd pwd;
char *buf = NULL;
buf = malloc(bufsize);
if (buf == NULL) {
D("failed to allocate passwd buf(%ld)\n", bufsize);
- set_static_userinfo();
+ set_static_sdk_userinfo();
} else {
if (sdbd_get_user_pwd(SDK_USER_NAME, &pwd, buf, bufsize) < 0) {
D("get user passwd info.(errno: %d)\n", errno);
- set_static_userinfo();
+ set_static_sdk_userinfo();
} else {
D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
}
init_sdk_userinfo();
+ init_root_userinfo();
if (g_sdk_home_dir != NULL && stat(g_sdk_home_dir, &st) == 0) {
if (st.st_uid != g_sdk_user_id || st.st_gid != g_sdk_group_id) {
"%s", DISABLED);
}
+ // Sdbd root permission
+ snprintf(g_capabilities.root_permission, sizeof(g_capabilities.root_permission),
+ "%s", DISABLED);
// Root command support
if(!request_capability_to_plugin(CAPABILITY_ROOT_ONOFF, g_capabilities.rootonoff_support,
"%s", UNKNOWN);
}
+ // appid2pid support
+ ret = is_appid2pid_supported();
+ snprintf(g_capabilities.appid2pid_support, sizeof(g_capabilities.appid2pid_support),
+ "%s", ret == 1 ? ENABLED : DISABLED);
+
+ // pkgcmd debug mode support
+ if(!request_capability_to_plugin(CAPABILITY_DEBUGMODE, g_capabilities.pkgcmd_debugmode,
+ sizeof(g_capabilities.pkgcmd_debugmode))) {
+ D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_DEBUGMODE);
+ snprintf(g_capabilities.pkgcmd_debugmode, sizeof(g_capabilities.pkgcmd_debugmode),
+ "%s", ENABLED);
+ }
+
// Capability version
snprintf(g_capabilities.sdbd_cap_version, sizeof(g_capabilities.sdbd_cap_version),
"%d.%d", SDBD_CAP_VERSION_MAJOR, SDBD_CAP_VERSION_MINOR);