From a2ed67457f3df4457c73a09be8a4dfd51fc735aa Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Wed, 8 Feb 2017 15:39:52 +0900 Subject: [PATCH 01/16] sdb.h: remove duplicated member Change-Id: I11f7086dd60cefbe36be2a46b9e92e2585b14cf1 Signed-off-by: Sooyoung Ha --- src/sdb.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sdb.h b/src/sdb.h index 0c4f7cc..b339f26 100644 --- a/src/sdb.h +++ b/src/sdb.h @@ -296,7 +296,6 @@ typedef struct platform_capabilities char sdbd_version[CAPBUF_ITEMSIZE]; // sdbd version char sdbd_plugin_version[CAPBUF_ITEMSIZE]; // sdbd plugin version char sdbd_cap_version[CAPBUF_ITEMSIZE]; // capability version - char pkgcmd_debugmode[CAPBUF_ITEMSIZE]; // enabled or disabled } pcap; extern pcap g_capabilities; -- 2.7.4 From c6a355e91b476b40205f8e7f7339bd54e1775b36 Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Wed, 8 Feb 2017 16:05:57 +0900 Subject: [PATCH 02/16] package: update version (3.0.15) Change-Id: I0085cc5980ebf1679f2c0193953c380831cd9ac7 Signed-off-by: Sooyoung Ha --- packaging/sdbd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 1374f57..6a2476b 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.14 +Version: 3.0.15 Release: 0 License: Apache-2.0 Summary: SDB daemon -- 2.7.4 From de9f966ccc66386af2643b9645f8eca73ef64cd0 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Fri, 5 Aug 2016 15:20:34 +0900 Subject: [PATCH 03/16] Add capability 'sdbd_rootperm' Change-Id: Ib63b4f3605506f62e3a8e8d7e32fb5937062ca3c Signed-off-by: shingil.kang Signed-off-by: Sooyoung Ha --- src/sdb.c | 3 +++ src/sdb.h | 1 + src/services.c | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/src/sdb.c b/src/sdb.c index 6d2bf42..692e87f 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -1873,6 +1873,9 @@ static void init_capabilities(void) { "%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, diff --git a/src/sdb.h b/src/sdb.h index b339f26..2128616 100644 --- a/src/sdb.h +++ b/src/sdb.h @@ -281,6 +281,7 @@ typedef struct platform_capabilities char encryption_support[CAPBUF_ITEMSIZE]; // enabled or disabled char appid2pid_support[CAPBUF_ITEMSIZE]; // enabled or disabled char pkgcmd_debugmode[CAPBUF_ITEMSIZE]; // enabled or disabled + char root_permission[CAPBUF_ITEMSIZE]; // enabled or disabled char log_enable[CAPBUF_ITEMSIZE]; // enabled or disabled char log_path[CAPBUF_LL_ITEMSIZE]; // path of sdbd log diff --git a/src/services.c b/src/services.c index cafffc9..64dbd11 100644 --- a/src/services.c +++ b/src/services.c @@ -893,6 +893,10 @@ static void get_capability(int fd, void *cookie) { offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, "syncwinsz_support", g_capabilities.syncwinsz_support); + // sdbd root permission + offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, + "sdbd_rootperm", g_capabilities.root_permission); + // Root command support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, "rootonoff_support", g_capabilities.rootonoff_support); -- 2.7.4 From e51486b368ca9d8ffd57f569903c8bad2d04dcf8 Mon Sep 17 00:00:00 2001 From: "shingil.kang" Date: Wed, 13 Jul 2016 14:20:27 +0900 Subject: [PATCH 04/16] Allowed 'sdb root on' command even if the UID of SDBD is non-root. - file IO(pull/push), shell service can be worked by root user with restricted priviliges. Change-Id: I37f4248443bd7f5231ec99e0d1737cd556b749b3 Signed-off-by: shingil.kang Signed-off-by: Sooyoung Ha --- src/file_sync_service.c | 17 +++--- src/sdb.c | 136 ++++++++++++++++++++++++++++++++++++++++-------- src/sdb.h | 17 +++++- src/services.c | 31 +++++------ 4 files changed, 151 insertions(+), 50 deletions(-) diff --git a/src/file_sync_service.c b/src/file_sync_service.c index 81f6841..1675cd2 100644 --- a/src/file_sync_service.c +++ b/src/file_sync_service.c @@ -159,7 +159,7 @@ static void sync_read_label_notify(int s) char *path = buffer; path++; path++; - // set_syncfile_smack_label(path); + //set_syncfile_smack_label(path); } } @@ -653,6 +653,14 @@ void file_sync_service(int fd, void *cookie) goto fail; } + if (should_drop_privileges()) { + if (set_sdk_user_privileges(DROP_CAPABILITIES_AFTER_FORK) < 0) { + goto fail; + } + } else { + set_root_privileges(); + } + for(;;) { D("sync: waiting for command for %d sec\n", SYNC_TIMEOUT); @@ -690,13 +698,6 @@ void file_sync_service(int fd, void *cookie) D("sync: '%s' '%s'\n", (char*) &msg.req, name); - if (should_drop_privileges() && !verify_sync_rule(name)) { - if (getuid() != g_sdk_user_id && set_sdk_user_privileges() < 0) { - fail_message(fd, "failed to set SDK user privileges."); - goto fail; - } - } - switch(msg.req.id) { case ID_STAT: if(do_stat(fd, name)) goto fail; diff --git a/src/sdb.c b/src/sdb.c index 692e87f..0e3a297 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -73,6 +73,8 @@ SDB_MUTEX_DEFINE( D_lock ); #endif int HOST = 0; + +// sdk user uid_t g_sdk_user_id; gid_t g_sdk_group_id; char* g_sdk_home_dir = NULL; @@ -81,6 +83,12 @@ pcap g_capabilities; 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; @@ -93,6 +101,7 @@ struct group_info g_default_groups[] = { {"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; @@ -1565,40 +1574,40 @@ void register_bootdone_cb() { } } -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); @@ -1645,13 +1654,25 @@ static int sdbd_get_group(const char* group_name, struct group* grp, char* buf, 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; } @@ -1664,6 +1685,9 @@ int set_sdk_user_privileges() { 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) { @@ -1678,6 +1702,32 @@ int set_sdk_user_privileges() { 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; @@ -1727,12 +1777,53 @@ static int init_sdb_default_groups() { 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; @@ -1750,11 +1841,11 @@ static int init_sdk_userinfo() { 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); @@ -1791,6 +1882,7 @@ static void init_sdk_requirements() { } 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) { diff --git a/src/sdb.h b/src/sdb.h index 2128616..0fe7005 100644 --- a/src/sdb.h +++ b/src/sdb.h @@ -419,12 +419,22 @@ extern uid_t g_sdk_user_id; extern gid_t g_sdk_group_id; extern char* g_sdk_home_dir; extern char* g_sdk_home_dir_env; + +#define ROOT_USER_NAME "root" +#define STATIC_ROOT_USER_ID 0 +#define STATIC_ROOT_GROUP_ID 0 +#define STATIC_ROOT_HOME_DIR "/root" +extern uid_t g_root_user_id; +extern gid_t g_root_group_id; +extern char* g_root_home_dir; +extern char* g_root_home_dir_env; + #endif int should_drop_privileges(void); -int set_sdk_user_privileges(); -void set_root_privileges(); void send_device_status(); +int set_sdk_user_privileges(int is_drop_capability_after_fork); +int set_root_privileges(); int get_emulator_forward_port(void); int get_emulator_name(char str[], int str_size); @@ -553,3 +563,6 @@ int read_line(const int fd, char* ptr, const size_t maxlen); int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[]); void get_env(char *key, char **env); +#define RESERVE_CAPABILITIES_AFTER_FORK 0 +#define DROP_CAPABILITIES_AFTER_FORK 1 + diff --git a/src/services.c b/src/services.c index 64dbd11..da73ff6 100644 --- a/src/services.c +++ b/src/services.c @@ -147,24 +147,17 @@ void rootshell_service(int fd, void *cookie) char *mode = (char*) cookie; if (!strcmp(mode, "on")) { - if (getuid() == 0) { - if (rootshell_mode == 1) { - //snprintf(buf, sizeof(buf), "Already changed to sdk user mode\n"); - // do not show message + if (rootshell_mode == 1) { + //snprintf(buf, sizeof(buf), "Already changed to sdk user mode\n"); + // do not show message + } else { + if (is_support_rootonoff()) { + rootshell_mode = 1; + //allows a permitted user to execute a command as the superuser + snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n"); } else { - if (is_support_rootonoff()) { - rootshell_mode = 1; - //allows a permitted user to execute a command as the superuser - snprintf(buf, sizeof(buf), "Switched to 'root' account mode\n"); - } else { - snprintf(buf, sizeof(buf), "Permission denied\n"); - } - writex(fd, buf, strlen(buf)); + snprintf(buf, sizeof(buf), "Permission denied\n"); } - } else { - D("need root permission for root shell: %d\n", getuid()); - rootshell_mode = 0; - snprintf(buf, sizeof(buf), "Permission denied\n"); writex(fd, buf, strlen(buf)); } } else if (!strcmp(mode, "off")) { @@ -445,15 +438,17 @@ int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * c } if (should_drop_privileges()) { - if (argv[2] != NULL && getuid() == 0 && request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_ROOTCMD, argv[2])) { + if (argv[2] != NULL && request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_ROOTCMD, argv[2])) { // do nothing D("sdb: executes root commands!!:%s\n", argv[2]); } else { - if (getuid() != g_sdk_user_id && set_sdk_user_privileges() < 0) { + if (getuid() != g_sdk_user_id && set_sdk_user_privileges(RESERVE_CAPABILITIES_AFTER_FORK) < 0) { fprintf(stderr, "failed to set SDK user privileges\n"); exit(-1); } } + } else { + set_root_privileges(); } redirect_and_exec(pts, cmd, argv, envp); fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n", -- 2.7.4 From f8e0f4153bee5b958a43e0c6cccb21d67d24a142 Mon Sep 17 00:00:00 2001 From: Shingil Kang Date: Tue, 12 Jul 2016 22:18:27 -0700 Subject: [PATCH 05/16] Revert "Revert "Modify modules that need root permission."" This reverts commit 9395230cf70cc07bfd036f8aa374f5f9443c7983. Change-Id: I3fb22370706706e8e8042fedd58b79d95b889946 Signed-off-by: Sooyoung Ha --- packaging/sdbd_device.service | 2 ++ packaging/sdbd_emulator.service | 2 ++ src/file_sync_service.c | 62 ----------------------------------------- 3 files changed, 4 insertions(+), 62 deletions(-) diff --git a/packaging/sdbd_device.service b/packaging/sdbd_device.service index 0537fcd..b47e8f3 100644 --- a/packaging/sdbd_device.service +++ b/packaging/sdbd_device.service @@ -4,6 +4,8 @@ Requires=tizen-system-env.service After=tmp.mount [Service] +User=sdk +Group=sdk Type=forking #location of SDBD log file EnvironmentFile=-/run/tizen-system-env diff --git a/packaging/sdbd_emulator.service b/packaging/sdbd_emulator.service index 2129436..6e0ec0f 100644 --- a/packaging/sdbd_emulator.service +++ b/packaging/sdbd_emulator.service @@ -5,6 +5,8 @@ After=tmp.mount dbus.service #DefaultDependencies=false [Service] +User=sdk +Group=sdk Type=forking #location of SDBD log file Environment=DISPLAY=:0 diff --git a/src/file_sync_service.c b/src/file_sync_service.c index 1675cd2..b2c2f4c 100644 --- a/src/file_sync_service.c +++ b/src/file_sync_service.c @@ -41,42 +41,11 @@ #define SYNC_TIMEOUT 15 -struct sync_permit_rule -{ - const char *name; - char *regx; - int mode; // 0:push, 1: pull, 2: push&push -}; - -struct sync_permit_rule sdk_sync_permit_rule[] = { - /* 0 */ {"unitest", "", 1}, - /* 1 */ {"codecoverage", "", 1}, - /* 2 */ {"da", "", 1}, - /* end */ {NULL, NULL, 0} -}; - /* The typical default value for the umask is S_IWGRP | S_IWOTH (octal 022). * Before use the DIR_PERMISSION, the process umask value should be set 0 using umask(). */ #define DIR_PERMISSION 0777 -void init_sdk_sync_permit_rule_regx(void) -{ - int ret; - ret = asprintf(&sdk_sync_permit_rule[0].regx, "^((/tmp)|(%s)|(%s))/[a-zA-Z0-9]{10}/data/[a-zA-Z0-9_\\-]{1,50}\\.xml$", APP_INSTALL_PATH_PREFIX1, APP_INSTALL_PATH_PREFIX2); - if(ret < 0) { - D("failed to run asprintf for unittest\n"); - } - ret = asprintf(&sdk_sync_permit_rule[1].regx, "^((/tmp)|(%s)|(%s))/[a-zA-Z0-9]{10}/data/+(.)*\\.gcda$", APP_INSTALL_PATH_PREFIX1, APP_INSTALL_PATH_PREFIX2); - if (ret < 0) { - D("failed to run asprintf for codecoverage\n"); - } - ret = asprintf(&sdk_sync_permit_rule[2].regx, "^(/tmp/da/)*+[a-zA-Z0-9_\\-\\.]{1,50}\\.png$"); - if (ret < 0) { - D("failed to run asprintf for da\n"); - } -} - #if 0 static void set_syncfile_smack_label(char *src) { char *label_transmuted = NULL; @@ -592,37 +561,6 @@ static int do_recv(int s, const char *path, char *buffer) return 0; } -static int verify_sync_rule(const char* path) { - regex_t regex; - int ret; - char buf[PATH_MAX]; - int i=0; - - init_sdk_sync_permit_rule_regx(); - for (i=0; sdk_sync_permit_rule[i].regx != NULL; i++) { - ret = regcomp(®ex, sdk_sync_permit_rule[i].regx, REG_EXTENDED); - if(ret){ - return 0; - } - // execute regular expression - ret = regexec(®ex, path, 0, NULL, 0); - if(!ret){ - regfree(®ex); - D("found matched rule(%s) from %s path\n", sdk_sync_permit_rule[i].name, path); - return 1; - } else if( ret == REG_NOMATCH ){ - // do nothin - } else{ - regerror(ret, ®ex, buf, sizeof(buf)); - D("regex match failed(%s): %s\n",sdk_sync_permit_rule[i].name, buf); - } - } - regfree(®ex); - for (i=0; sdk_sync_permit_rule[i].regx != NULL; i++){ - free(sdk_sync_permit_rule[i].regx); - } - return 0; -} void file_sync_service(int fd, void *cookie) { -- 2.7.4 From 400c941ab0c774bf93774d463ce37ff90afad7ef Mon Sep 17 00:00:00 2001 From: Shingil Kang Date: Tue, 12 Jul 2016 22:18:07 -0700 Subject: [PATCH 06/16] Revert "Revert "sdb: change group and owner of sdb device node"" This reverts commit 45bfe8e57fd16c8bc2ad8073afeb3a842c3eb810. Change-Id: Iecfb11a43fb26135cc4f99260892d7edd1e69722 Signed-off-by: Sooyoung Ha --- packaging/sdbd.spec | 4 ++++ rules/99-sdbd.rules | 1 + 2 files changed, 5 insertions(+) create mode 100644 rules/99-sdbd.rules diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 6a2476b..74888df 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -84,6 +84,9 @@ install -m 0644 %SOURCE1001 %{buildroot}%{_unitdir}/sdbd.service install -m 0644 %SOURCE1004 %{buildroot}%{_unitdir}/sdbd_tcp.service mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants ln -s %{_unitdir}/sdbd.service %{buildroot}/%{_unitdir}/multi-user.target.wants/ + +mkdir -p %{buildroot}%{_prefix}/lib/udev/rules.d/ +install -m 644 rules/99-sdbd.rules %{buildroot}%{_prefix}/lib/udev/rules.d/ %endif mkdir -p %{buildroot}%{_prefix}/sbin @@ -126,6 +129,7 @@ chsmack -e "User::Shell" /bin/sh-user %else %{_unitdir}/sdbd_tcp.service %{_unitdir}/multi-user.target.wants/sdbd.service +%{_prefix}/lib/udev/rules.d/99-sdbd.rules %endif /usr/share/license/%{name} %{TZ_SYS_BIN}/profile_command diff --git a/rules/99-sdbd.rules b/rules/99-sdbd.rules new file mode 100644 index 0000000..c441d87 --- /dev/null +++ b/rules/99-sdbd.rules @@ -0,0 +1 @@ +KERNEL=="samsung_sdb", OWNER="sdk", GROUP="sdk", SECLABEL{smack}="*" -- 2.7.4 From f67a8533da66deabfa20ed445cfd9951ac83e81c Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Wed, 15 Feb 2017 16:07:02 +0900 Subject: [PATCH 07/16] source: remove redundant code Remove some duplicated codes and redundant spaces. Change-Id: I4c42490f999eb587f7adca17b3322ca900af50c1 Signed-off-by: Sooyoung Ha --- src/sdb.c | 17 +++++------------ src/services.c | 49 +++++++++++++++++++++++-------------------------- 2 files changed, 28 insertions(+), 38 deletions(-) diff --git a/src/sdb.c b/src/sdb.c index 0e3a297..5c6b2d5 100644 --- a/src/sdb.c +++ b/src/sdb.c @@ -1987,15 +1987,6 @@ static void init_capabilities(void) { } - // 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); - } - - // Zone support ret = is_container_enabled(); snprintf(g_capabilities.zone_support, sizeof(g_capabilities.zone_support), @@ -2134,11 +2125,13 @@ static void init_capabilities(void) { snprintf(g_capabilities.appid2pid_support, sizeof(g_capabilities.appid2pid_support), "%s", ret == 1 ? ENABLED : DISABLED); - // pkgcmd debug mode support - snprintf(g_capabilities.pkgcmd_debugmode, sizeof(g_capabilities.pkgcmd_debugmode), + 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), diff --git a/src/services.c b/src/services.c index da73ff6..e1a55df 100644 --- a/src/services.c +++ b/src/services.c @@ -866,87 +866,87 @@ static void get_capability(int fd, void *cookie) { // Secure protocol support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "secure_protocol", g_capabilities.secure_protocol); + "secure_protocol", g_capabilities.secure_protocol); // Interactive shell support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "intershell_support", g_capabilities.intershell_support); + "intershell_support", g_capabilities.intershell_support); // File push/pull support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "filesync_support", g_capabilities.filesync_support); + "filesync_support", g_capabilities.filesync_support); // USB protocol support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "usbproto_support", g_capabilities.usbproto_support); + "usbproto_support", g_capabilities.usbproto_support); // Socket protocol support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "sockproto_support", g_capabilities.sockproto_support); + "sockproto_support", g_capabilities.sockproto_support); // Window size synchronization support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "syncwinsz_support", g_capabilities.syncwinsz_support); + "syncwinsz_support", g_capabilities.syncwinsz_support); // sdbd root permission offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "sdbd_rootperm", g_capabilities.root_permission); + "sdbd_rootperm", g_capabilities.root_permission); // Root command support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "rootonoff_support", g_capabilities.rootonoff_support); + "rootonoff_support", g_capabilities.rootonoff_support); // Encryption support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "encryption_support", g_capabilities.encryption_support); + "encryption_support", g_capabilities.encryption_support); // Zone support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "zone_support", g_capabilities.zone_support); + "zone_support", g_capabilities.zone_support); // Multi-User support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "multiuser_support", g_capabilities.multiuser_support); + "multiuser_support", g_capabilities.multiuser_support); // CPU Architecture of model offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "cpu_arch", g_capabilities.cpu_arch); + "cpu_arch", g_capabilities.cpu_arch); // SDK Tool path offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "sdk_toolpath", g_capabilities.sdk_toolpath); + "sdk_toolpath", g_capabilities.sdk_toolpath); // Profile name offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "profile_name", g_capabilities.profile_name); + "profile_name", g_capabilities.profile_name); // Vendor name offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "vendor_name", g_capabilities.vendor_name); + "vendor_name", g_capabilities.vendor_name); // Target name of the launch possible offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "can_launch", g_capabilities.can_launch); + "can_launch", g_capabilities.can_launch); // Platform version offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "platform_version", g_capabilities.platform_version); + "platform_version", g_capabilities.platform_version); // Product version offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "product_version", g_capabilities.product_version); + "product_version", g_capabilities.product_version); // Sdbd version offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "sdbd_version", g_capabilities.sdbd_version); + "sdbd_version", g_capabilities.sdbd_version); // Sdbd plugin version offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "sdbd_plugin_version", g_capabilities.sdbd_plugin_version); + "sdbd_plugin_version", g_capabilities.sdbd_plugin_version); // Capability version offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "sdbd_cap_version", g_capabilities.sdbd_cap_version); + "sdbd_cap_version", g_capabilities.sdbd_cap_version); // Sdbd log enable offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, @@ -956,20 +956,17 @@ static void get_capability(int fd, void *cookie) { offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, "log_path", g_capabilities.log_path); - offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "pkgcmd_debugmode", g_capabilities.pkgcmd_debugmode); - // Application command support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, "appcmd_support", g_capabilities.appcmd_support); // appid2pid support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "appid2pid_support", g_capabilities.appid2pid_support); + "appid2pid_support", g_capabilities.appid2pid_support); // pkgcmd debug mode support offset += put_key_value_string(cap_buffer, offset, CAPBUF_SIZE, - "pkgcmd_debugmode", g_capabilities.pkgcmd_debugmode); + "pkgcmd_debugmode", g_capabilities.pkgcmd_debugmode); offset++; // for '\0' character -- 2.7.4 From 6e86939b66f46597af5f6017a856bd69cc50c87c Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Sat, 25 Feb 2017 23:45:51 +0900 Subject: [PATCH 08/16] shell: introduce sdb user daemon for user shell To create a shell session via sdb, SDBD open the ptmx and then a pts device is created. Next, SDBD forks a shell who use the pts opened previously. BUT, forked shell cannot use the pts because forked shell has no privilege to read the pts. So I introduce new sdb user daemon who is only for launching shell. The sdb user daemon has low privilege, same as user shell, and has few functions - open ptmx, pass opened ptmx fd to SDBD, and exec shell. Change-Id: I2332419e4b186d4b18c281a554569735617e9f64 Signed-off-by: Sooyoung Ha --- CMakeLists.txt | 129 +++++++++++++------------- packaging/sdbd.spec | 3 + packaging/sdbd_emulator.service | 1 - src/services.c | 163 ++++++++++++++++++++------------ src/subprocess.c | 199 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 372 insertions(+), 123 deletions(-) create mode 100644 src/subprocess.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e16df2d..64c56f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,51 +27,54 @@ INCLUDE(FindPkgConfig) ############################# compiler flags ################################## SET(SDBD_SRCS - src/sdb.c - src/fdevent.c - src/transport.c - src/transport_local.c - src/transport_usb.c - src/sockets.c - src/services.c - src/file_sync_service.c - src/usb_linux_client.c - src/utils.c - src/socket_inaddr_any_server.c - src/socket_local_client.c - src/socket_local_server.c - src/socket_loopback_client.c - src/socket_loopback_server.c - src/socket_network_client.c - src/sdktools.c - src/strutils.c - src/init.c - src/fileutils.c - src/commandline_sdbd.c - src/usb_linux_client.c - src/usb_funcfs_client.c - src/default_plugin_auth.c - src/default_plugin_basic.c - src/default_plugin_main.c - src/default_plugin_event.c - src/default_plugin_appcmd.c - src/hashtable.c - src/plugin.c - src/plugin_encrypt.c + src/sdb.c + src/fdevent.c + src/transport.c + src/transport_local.c + src/transport_usb.c + src/sockets.c + src/services.c + src/file_sync_service.c + src/usb_linux_client.c + src/utils.c + src/socket_inaddr_any_server.c + src/socket_local_client.c + src/socket_local_server.c + src/socket_loopback_client.c + src/socket_loopback_server.c + src/socket_network_client.c + src/sdktools.c + src/strutils.c + src/init.c + src/fileutils.c + src/commandline_sdbd.c + src/usb_linux_client.c + src/usb_funcfs_client.c + src/default_plugin_auth.c + src/default_plugin_basic.c + src/default_plugin_main.c + src/default_plugin_event.c + src/default_plugin_appcmd.c + src/hashtable.c + src/plugin.c + src/plugin_encrypt.c +) +SET(SDBD_SUBS + src/subprocess.c ) include(FindPkgConfig) pkg_check_modules(pkgs REQUIRED - libtzplatform-config - capi-system-info - vconf - glib-2.0 - dbus-1 - dbus-glib-1 - dlog - ) - + libtzplatform-config + capi-system-info + vconf + glib-2.0 + dbus-1 + dbus-glib-1 + dlog +) + FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) @@ -90,54 +93,56 @@ ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64") ADD_DEFINITIONS("-DSUPPORT_ENCRYPT") IF (_ARM_TARGET) - ADD_DEFINITIONS("-DANDROID_GADGET=1") + ADD_DEFINITIONS("-DANDROID_GADGET=1") ENDIF (_ARM_TARGET) IF(TARGET_ARCH STREQUAL x86) - ADD_DEFINITIONS("-DTARGET_ARCH_X86") + ADD_DEFINITIONS("-DTARGET_ARCH_X86") ELSE() - ADD_DEFINITIONS("-DTARGET_ARCH_ARM") + ADD_DEFINITIONS("-DTARGET_ARCH_ARM") ENDIF() IF(WEARABLE_PROFILE STREQUAL on) - ADD_DEFINITIONS("-D_WEARABLE") + ADD_DEFINITIONS("-D_WEARABLE") ENDIF() find_package(Threads REQUIRED) ADD_EXECUTABLE(sdbd ${SDBD_SRCS}) +ADD_EXECUTABLE(sdbd-user ${SDBD_SUBS}) TARGET_LINK_LIBRARIES(sdbd -pie -lsmack -lresolv -ldl ${CMAKE_THREAD_LIBS_INIT} ${pkgs_LDFLAGS}) +TARGET_LINK_LIBRARIES(sdbd-user -pie ${CMAKE_THREAD_LIBS_INIT} ${pkgs_LDFLAGS}) set_property( - TARGET sdbd - PROPERTY COMPILE_DEFINITIONS - SDB_HOST=0 - _DROP_PRIVILEGE - _FILE_OFFSET_BITS=64 + TARGET sdbd + PROPERTY COMPILE_DEFINITIONS + SDB_HOST=0 + _DROP_PRIVILEGE + _FILE_OFFSET_BITS=64 ) set_property( - TARGET sdbd - APPEND PROPERTY COMPILE_DEFINITIONS - _XOPEN_SOURCE - _GNU_SOURCE - HAVE_FORKEXEC + TARGET sdbd + APPEND PROPERTY COMPILE_DEFINITIONS + _XOPEN_SOURCE + _GNU_SOURCE + HAVE_FORKEXEC ) if(USE_FUNCTION_FS) - set_property( - TARGET sdbd - APPEND PROPERTY COMPILE_DEFINITIONS - USB_FUNCFS - ) + set_property( + TARGET sdbd + APPEND PROPERTY COMPILE_DEFINITIONS + USB_FUNCFS + ) endif() -install(TARGETS sdbd DESTINATION /usr/sbin) +install(TARGETS sdbd sdbd-user DESTINATION /usr/sbin) install(FILES script/sdbd DESTINATION /etc/init.d) # Optionally build unit tests binary -- could be helpful during further development if(BUILD_UNIT_TESTS) - enable_testing() - add_subdirectory(test) + enable_testing() + add_subdirectory(test) endif() diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 74888df..e595e8c 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -115,12 +115,15 @@ fi cp -f /bin/sh /bin/sh-user chsmack -a "_" /bin/sh-user chsmack -e "User::Shell" /bin/sh-user +chsmack -a "_" /sbin/sdbd-user +chsmack -e "User::Shell" /sbin/sdbd-user %files %manifest sdbd.manifest %license LICENSE %defattr(-,root,root,-) %{_prefix}/sbin/sdbd +%{_prefix}/sbin/sdbd-user %{_prefix}/sbin/sdk_launch %attr(0755, root, root) %{_sysconfdir}/init.d/sdbd %{_unitdir}/sdbd.service diff --git a/packaging/sdbd_emulator.service b/packaging/sdbd_emulator.service index 6e0ec0f..abd1605 100644 --- a/packaging/sdbd_emulator.service +++ b/packaging/sdbd_emulator.service @@ -8,7 +8,6 @@ After=tmp.mount dbus.service User=sdk Group=sdk Type=forking -#location of SDBD log file Environment=DISPLAY=:0 PIDFile=/tmp/.sdbd.pid RemainAfterExit=yes diff --git a/src/services.c b/src/services.c index e1a55df..f395fca 100644 --- a/src/services.c +++ b/src/services.c @@ -39,6 +39,8 @@ # include # include "sdktools.h" #endif +#include +#include #include "strutils.h" #include "utils.h" @@ -369,102 +371,142 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) } #if !SDB_HOST - -static void redirect_and_exec(int pts, const char *cmd, char * const argv[], char * const envp[]) +/* receive the ptm from child, sdbd-user */ +static ssize_t recv_fd(int fd, void *ptr, size_t nbytes, int *recvfd) { - dup2(pts, 0); - dup2(pts, 1); - dup2(pts, 2); + struct msghdr msg; + struct iovec iov[1]; + struct cmsghdr *pheader; + union { + struct cmsghdr cmhdr; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + ssize_t ret; + + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + iov[0].iov_base = ptr; + iov[0].iov_len = nbytes; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + if ((ret = recvmsg(fd, &msg, 0)) <= 0) { + return ret; + } - sdb_close(pts); + if ((pheader = CMSG_FIRSTHDR(&msg)) != NULL && + pheader->cmsg_len == CMSG_LEN(sizeof(int))) { + if (pheader->cmsg_level != SOL_SOCKET) { + D("sdb: control level != SOL_SOCKET"); + exit(-1); + } + if (pheader->cmsg_type != SCM_RIGHTS) { + D("sdb: control type != SCM_RIGHTS"); + exit(-1); + } + memcpy(recvfd, CMSG_DATA(pheader), sizeof(int)); + } else { + *recvfd = -1; + } - execve(cmd, argv, envp); + return ret; } int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[]) { - char devname[64]; - int ptm; - - ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); - if(ptm < 0){ - D("[ cannot open /dev/ptmx - errno:%d ]\n",errno); - return -1; - } - if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) { - D("[ cannot set cloexec to /dev/ptmx - errno:%d ]\n",errno); - } - - if(grantpt(ptm) || unlockpt(ptm) || - ptsname_r(ptm, devname, sizeof(devname)) != 0 ){ - D("[ trouble with /dev/ptmx - errno:%d ]\n", errno); - sdb_close(ptm); - return -1; - } - *pid = fork(); if(*pid < 0) { D("- fork failed: errno:%d -\n", errno); - sdb_close(ptm); return -1; } - if(*pid == 0){ - int pts; - - setsid(); - - pts = unix_open(devname, O_RDWR); - if(pts < 0) { - fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname); - exit(-1); - } - - sdb_close(ptm); - - // set OOM adjustment to zero - { - char text[64]; - //snprintf(text, sizeof text, "/proc/%d/oom_score_adj", getpid()); - snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); - int fd = sdb_open(text, O_WRONLY); - if (fd >= 0) { - sdb_write(fd, "0", 1); - sdb_close(fd); - } else { - // FIXME: not supposed to be here - D("sdb: unable to open %s due to errno:%d\n", text, errno); - } - } - + if (*pid == 0) { if (should_drop_privileges()) { if (argv[2] != NULL && request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_ROOTCMD, argv[2])) { // do nothing D("sdb: executes root commands!!:%s\n", argv[2]); } else { if (getuid() != g_sdk_user_id && set_sdk_user_privileges(RESERVE_CAPABILITIES_AFTER_FORK) < 0) { - fprintf(stderr, "failed to set SDK user privileges\n"); + D("failed to set SDK user privileges\n"); exit(-1); } } } else { set_root_privileges(); } - redirect_and_exec(pts, cmd, argv, envp); - fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n", - cmd, errno); + /* exec sdbduser */ + execve(cmd, argv, envp); + D("- exec '%s' failed: (errno:%d) -\n", cmd, errno); exit(-1); } else { // Don't set child's OOM adjustment to zero. // Let the child do it itself, as sometimes the parent starts // running before the child has a /proc/pid/oom_adj. // """sdb: unable to open /proc/644/oom_adj""" seen in some logs. + char tmptext[32]; + int ptm = -1; + struct sockaddr_un addr; + int sock; + int trycnt = 1; + + /* The child process will open .sdbduser_pid.sock socket. + This socket transfers the ptm fd that was opened by child process. + You can see related code on subprocess.c file. */ + snprintf(tmptext, sizeof tmptext, "/tmp/.sdbduser_%d.sock", (int)(*pid)); + char *sockpath = strdup(tmptext); + if (sockpath == NULL) { + D("failed to get socket path, %s\n", strerror(errno)); + return -1; + } + D("read fd socket is %s\n", sockpath); + + sock = socket(PF_LOCAL, SOCK_STREAM, 0); + if (sock == -1) { + D("socket error, %s\n", strerror(errno)); + free(sockpath); + return -1; + } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_LOCAL; + strcpy(addr.sun_path, sockpath); + int slen = offsetof(struct sockaddr_un, sun_path) + strlen(sockpath); + while (connect(sock, (struct sockaddr *)&addr, slen) == -1 + && trycnt < 100) { + D("try to connect socket %s, %d times.\n", sockpath, trycnt++); + /* sleep maximum 100 times */ + usleep(10000); + } + if (trycnt == 100) { + D("failed to connect, err: %s\n", strerror(errno)); + free(sockpath); + return -1; + } + + char c; + if (recv_fd(sock, &c, 1, &ptm) == -1) { + D("recv_fd error, %s\n", strerror(errno)); + free(sockpath); + return -1; + } else { + D("got ptm fd from child, fd: %d\n", ptm); + } + + if (sdb_close(sock) == -1) { + D("close sock error, %s\n", strerror(errno)); + } + free(sockpath); + + D("getting child's ptm successed.\n"); return ptm; } } #endif /* !SDB_HOST */ -#define SHELL_COMMAND "/bin/sh-user" +#define SHELL_COMMAND "/usr/sbin/sdbd-user" #define LOGIN_COMMAND "/bin/login" #define SUPER_USER "root" #define LOGIN_CONFIG "/etc/login.defs" @@ -478,6 +520,7 @@ static void subproc_waiter_service(int fd, void *cookie) for (;;) { int status; pid_t p = waitpid(pid, &status, 0); + D("entered fd=%d, post waitpid(pid=%d)\n", fd, p); if (p == pid) { D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status); if (WIFEXITED(status)) { diff --git a/src/subprocess.c b/src/subprocess.c new file mode 100644 index 0000000..c5d4bbd --- /dev/null +++ b/src/subprocess.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2017 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. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "sysdeps.h" +#include "sdb.h" + +#define SHELL_COMMAND "/bin/sh-user" + +/* to send ptm fd to sdbd main */ +static ssize_t send_fd(int fd, void *ptr, size_t nbytes, int sendfd) +{ + struct msghdr msg; + struct iovec iov[1]; + struct cmsghdr *pheader; + union { + struct cmsghdr cmhdr; + char control[CMSG_SPACE(sizeof(int))]; + } control_un; + + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + pheader = CMSG_FIRSTHDR(&msg); + pheader->cmsg_len = CMSG_LEN(sizeof(int)); + pheader->cmsg_level = SOL_SOCKET; + pheader->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(pheader), &sendfd, sizeof(int)); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + iov[0].iov_base = ptr; + iov[0].iov_len = nbytes; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + return sendmsg(fd, &msg, 0); +} + +static void redirect_and_exec(int pts, const char *cmd, char * const argv[], char * const envp[]) +{ + dup2(pts, 0); + dup2(pts, 1); + dup2(pts, 2); + + sdb_close(pts); + + execve(cmd, argv, envp); +} + +int main (int argc, char **argv, char **envp) +{ + char devname[16]; + int ptm; + pid_t pid; + int ret = -1; + + ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); + if(ptm < 0){ + fprintf(stderr, "sdbu cannot open /dev/ptmx, errno: %d\n",errno); + return ret; + } + + if(grantpt(ptm) || unlockpt(ptm) || + ptsname_r(ptm, devname, sizeof(devname)) != 0 ){ + fprintf(stderr, "sdbu trouble with /dev/ptmx, errno: %d\n", errno); + sdb_close(ptm); + return ret; + } + fprintf(stderr, "sdbu ptm opening success\n"); + + pid = fork(); + if(pid < 0) { + fprintf(stderr, "sdbu fork failed, errno: %d\n", errno); + sdb_close(ptm); + return ret; + } + + /* sdbd-user's child. + This just open pts and exec sh-user */ + if (pid == 0) { + int pts; + setsid(); + pts = unix_open(devname, O_RDWR | O_CLOEXEC); + if(pts < 0) { + fprintf(stderr, "sdbu: child failed to open pseudo-term slave %s\n", devname); + exit(-1); + } + fprintf(stderr, "sdbu: child open pts %s\n", devname); + + sdb_close(ptm); + + // set OOM adjustment to zero + { + char tmptext[64]; + snprintf(tmptext, sizeof tmptext, "/proc/%d/oom_adj", getpid()); + int fd = sdb_open(tmptext, O_WRONLY | O_CLOEXEC); + if (fd >= 0) { + sdb_write(fd, "0", 1); + sdb_close(fd); + } else { + fprintf(stderr, "sdbu: child unable to open %s due to errno:%d\n", tmptext, errno); + } + } + + /* argv[0] should be /bin/sh-user. original data is /usr/sbin/sdbd-user */ + argv[0] = SHELL_COMMAND; + redirect_and_exec(pts, SHELL_COMMAND, argv, envp); + /* if exec error */ + fprintf(stderr, "sdbu: child exec %s failed, errno: %d\n", SHELL_COMMAND, errno); + exit(-1); + } else { + /* sdbd-user process. + This process open the ptm and unix socket to send ptm. */ + /* socket create and open and bind, listen, accept and send fd here. */ + char tmptext[32]; + struct sockaddr_un addr; + int sock, s; + char c; + pid_t mypid = getpid(); + + snprintf(tmptext, sizeof tmptext, "/tmp/.sdbduser_%d.sock", (int)mypid); + + char *sockpath = strdup(tmptext); + if (sockpath == NULL) { + fprintf(stderr, "sdbu socket path error, %s\n", strerror(errno)); + exit(-1); + } + + sock = socket(PF_LOCAL, SOCK_STREAM, 0); + if (sock == -1) { + fprintf(stderr, "sdbu socket error, %s\n", strerror(errno)); + } + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_LOCAL; + strcpy(addr.sun_path, sockpath); + int slen = offsetof(struct sockaddr_un, sun_path) + strlen(sockpath); + if (bind(sock, (struct sockaddr *)&addr, slen) == -1) { + fprintf(stderr, "sdbu socket bind error, %s\n", strerror(errno)); + } + if (listen(sock, 5) == -1) { + fprintf(stderr, "sdbu listen error, %s\n", strerror(errno)); + } + if ((s = sdb_socket_accept(sock, NULL, 0)) == -1) { + fprintf(stderr, "sdbu accept error, %s\n", strerror(errno)); + } + + /* send ptm fd to sdbd */ + if (send_fd(s, &c, 1, ptm) != 0) { + fprintf(stderr, "sdbu send fd error, %s\n", strerror(errno)); + } + + sdb_close(s); + sdb_close(sock); + sdb_unlink(sockpath); + free(sockpath); + /* socket end */ + + /* simply wait child */ + int status, ret; + ret = wait(&status); + fprintf(stderr, "sdbu pid %d has ", ret); + if (WIFEXITED(status)) { + fprintf(stderr, "terminated normally %d.\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + fprintf(stderr, "signaled %d.\n", WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + fprintf(stderr, "stopped.\n"); + } else if (WIFCONTINUED(status)) { + fprintf(stderr, "continued.\n"); + } else { + fprintf(stderr, "terminated abnormally.\n"); + } + return 0; + } +} -- 2.7.4 From 5376437fb0c9992e956a911b615c7af4fccde528 Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Thu, 9 Mar 2017 11:43:55 +0900 Subject: [PATCH 09/16] package: update version (3.0.16) Change-Id: I49f60d84a2a061c71cd1a884af73306ad52ddd35 Signed-off-by: Sooyoung Ha --- packaging/sdbd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index e595e8c..e6d9cc2 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.15 +Version: 3.0.16 Release: 0 License: Apache-2.0 Summary: SDB daemon -- 2.7.4 From b6363325de31ee37147c816716b65ee81d2aad62 Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Tue, 14 Mar 2017 19:50:13 +0900 Subject: [PATCH 10/16] source: remove some risky codes Some of these codes can cause the various defects. Change-Id: I5effcdba397a9f80583564ccb2f975205413543c Signed-off-by: Sooyoung Ha --- src/services.c | 18 ++++++++++++------ src/subprocess.c | 41 +++++++++++++++++++++++------------------ 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/services.c b/src/services.c index f395fca..f6c1df6 100644 --- a/src/services.c +++ b/src/services.c @@ -459,20 +459,20 @@ int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * c snprintf(tmptext, sizeof tmptext, "/tmp/.sdbduser_%d.sock", (int)(*pid)); char *sockpath = strdup(tmptext); if (sockpath == NULL) { - D("failed to get socket path, %s\n", strerror(errno)); + D("failed to get socket path, %d\n", errno); return -1; } D("read fd socket is %s\n", sockpath); sock = socket(PF_LOCAL, SOCK_STREAM, 0); if (sock == -1) { - D("socket error, %s\n", strerror(errno)); + D("socket error, %d\n", errno); free(sockpath); return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; - strcpy(addr.sun_path, sockpath); + s_strncpy(addr.sun_path, sockpath, strlen(sockpath)); int slen = offsetof(struct sockaddr_un, sun_path) + strlen(sockpath); while (connect(sock, (struct sockaddr *)&addr, slen) == -1 && trycnt < 100) { @@ -481,14 +481,20 @@ int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * c usleep(10000); } if (trycnt == 100) { - D("failed to connect, err: %s\n", strerror(errno)); + D("failed to connect, errno: %d\n", errno); + if (sdb_close(sock) == -1) { + D("close sock error, %d\n", errno); + } free(sockpath); return -1; } char c; if (recv_fd(sock, &c, 1, &ptm) == -1) { - D("recv_fd error, %s\n", strerror(errno)); + D("recv_fd error, %d\n", errno); + if (sdb_close(sock) == -1) { + D("close sock error, %d\n", errno); + } free(sockpath); return -1; } else { @@ -496,7 +502,7 @@ int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * c } if (sdb_close(sock) == -1) { - D("close sock error, %s\n", strerror(errno)); + D("close sock error, %d\n", errno); } free(sockpath); diff --git a/src/subprocess.c b/src/subprocess.c index c5d4bbd..24676a1 100644 --- a/src/subprocess.c +++ b/src/subprocess.c @@ -144,36 +144,41 @@ int main (int argc, char **argv, char **envp) snprintf(tmptext, sizeof tmptext, "/tmp/.sdbduser_%d.sock", (int)mypid); - char *sockpath = strdup(tmptext); - if (sockpath == NULL) { - fprintf(stderr, "sdbu socket path error, %s\n", strerror(errno)); - exit(-1); - } - sock = socket(PF_LOCAL, SOCK_STREAM, 0); if (sock == -1) { - fprintf(stderr, "sdbu socket error, %s\n", strerror(errno)); + fprintf(stderr, "sdbu socket error, %d\n", errno); + return -1; + } + + char *sockpath = strdup(tmptext); + if (sockpath == NULL) { + fprintf(stderr, "sdbu socket path error, %d\n", errno); + sdb_close(sock); + return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; - strcpy(addr.sun_path, sockpath); + strncpy(addr.sun_path, sockpath, strlen(sockpath)); int slen = offsetof(struct sockaddr_un, sun_path) + strlen(sockpath); if (bind(sock, (struct sockaddr *)&addr, slen) == -1) { - fprintf(stderr, "sdbu socket bind error, %s\n", strerror(errno)); + fprintf(stderr, "sdbu socket bind error, %d\n", errno); + goto socket_fail; } if (listen(sock, 5) == -1) { - fprintf(stderr, "sdbu listen error, %s\n", strerror(errno)); + fprintf(stderr, "sdbu listen error, %d\n", errno); + goto socket_fail; } if ((s = sdb_socket_accept(sock, NULL, 0)) == -1) { - fprintf(stderr, "sdbu accept error, %s\n", strerror(errno)); - } - - /* send ptm fd to sdbd */ - if (send_fd(s, &c, 1, ptm) != 0) { - fprintf(stderr, "sdbu send fd error, %s\n", strerror(errno)); + fprintf(stderr, "sdbu accept error, %d\n", errno); + goto socket_fail; + } else { + /* send ptm fd to sdbd */ + if (send_fd(s, &c, 1, ptm) != 0) { + fprintf(stderr, "sdbu send fd error, %d\n", errno); + } + sdb_close(s); } - - sdb_close(s); +socket_fail: sdb_close(sock); sdb_unlink(sockpath); free(sockpath); -- 2.7.4 From 3b4e3f755ff32f95c96950d5b6ed7b09f636924a Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Tue, 14 Mar 2017 20:55:48 +0900 Subject: [PATCH 11/16] package: update version (3.0.17) Change-Id: I11e16a48bb2367ea7ef4c97a3e8649734185799f Signed-off-by: Sooyoung Ha --- packaging/sdbd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index e6d9cc2..c0f2137 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.16 +Version: 3.0.17 Release: 0 License: Apache-2.0 Summary: SDB daemon -- 2.7.4 From 5ed9c5e515140d3818d29ee3b4854e715d21d320 Mon Sep 17 00:00:00 2001 From: Jinhyung Choi Date: Thu, 23 Mar 2017 15:46:20 +0900 Subject: [PATCH 12/16] subprocess: remove user shell sub-process uses /sh instead of a copy of it. Change-Id: I2f0eb13fe5f08ae4eb6b1f3e57fd6d4119d7e446 Signed-off-by: Jinhyung Choi --- packaging/sdbd.spec | 3 --- src/subprocess.c | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index c0f2137..7f6c4aa 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -112,9 +112,6 @@ if ! getent passwd "${TZ_SDK_USER_NAME}" > /dev/null; then done fi -cp -f /bin/sh /bin/sh-user -chsmack -a "_" /bin/sh-user -chsmack -e "User::Shell" /bin/sh-user chsmack -a "_" /sbin/sdbd-user chsmack -e "User::Shell" /sbin/sdbd-user diff --git a/src/subprocess.c b/src/subprocess.c index 24676a1..71d8e16 100644 --- a/src/subprocess.c +++ b/src/subprocess.c @@ -27,7 +27,7 @@ #include "sysdeps.h" #include "sdb.h" -#define SHELL_COMMAND "/bin/sh-user" +#define SHELL_COMMAND "/bin/sh" /* to send ptm fd to sdbd main */ static ssize_t send_fd(int fd, void *ptr, size_t nbytes, int sendfd) @@ -100,7 +100,7 @@ int main (int argc, char **argv, char **envp) } /* sdbd-user's child. - This just open pts and exec sh-user */ + This just open pts and exec sh */ if (pid == 0) { int pts; setsid(); @@ -126,7 +126,6 @@ int main (int argc, char **argv, char **envp) } } - /* argv[0] should be /bin/sh-user. original data is /usr/sbin/sdbd-user */ argv[0] = SHELL_COMMAND; redirect_and_exec(pts, SHELL_COMMAND, argv, envp); /* if exec error */ -- 2.7.4 From 22e59566403f3da5524919324b763df724b53ebb Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Sat, 25 Mar 2017 00:46:21 +0900 Subject: [PATCH 13/16] service: change method of create_process function On some case, System privileged shell is needed(ex: appcmd). I provide functions for creating System privileged process as create_subprocess() and create_userprocess() for User::Shell privileged. And I also clarify the equivocal definition name. Change-Id: Iac129b81e2534ec2a54dc29969098ca8014f582c Signed-off-by: Sooyoung Ha --- src/services.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 8 deletions(-) diff --git a/src/services.c b/src/services.c index f6c1df6..1daaa43 100644 --- a/src/services.c +++ b/src/services.c @@ -371,6 +371,100 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) } #if !SDB_HOST + +static void redirect_and_exec(int pts, const char *cmd, char * const argv[], char * const envp[]) +{ + dup2(pts, 0); + dup2(pts, 1); + dup2(pts, 2); + + sdb_close(pts); + + execve(cmd, argv, envp); +} + +int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[]) +{ + char devname[64]; + int ptm; + + ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); + if(ptm < 0){ + D("[ cannot open /dev/ptmx - errno:%d ]\n",errno); + return -1; + } + if (fcntl(ptm, F_SETFD, FD_CLOEXEC) < 0) { + D("[ cannot set cloexec to /dev/ptmx - errno:%d ]\n",errno); + } + + if(grantpt(ptm) || unlockpt(ptm) || + ptsname_r(ptm, devname, sizeof(devname)) != 0 ){ + D("[ trouble with /dev/ptmx - errno:%d ]\n", errno); + sdb_close(ptm); + return -1; + } + + *pid = fork(); + if(*pid < 0) { + D("- fork failed: errno:%d -\n", errno); + sdb_close(ptm); + return -1; + } + + if(*pid == 0){ + int pts; + + setsid(); + + pts = unix_open(devname, O_RDWR); + if(pts < 0) { + fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname); + exit(-1); + } + + sdb_close(ptm); + + // set OOM adjustment to zero + { + char text[64]; + //snprintf(text, sizeof text, "/proc/%d/oom_score_adj", getpid()); + snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); + int fd = sdb_open(text, O_WRONLY); + if (fd >= 0) { + sdb_write(fd, "0", 1); + sdb_close(fd); + } else { + // FIXME: not supposed to be here + D("sdb: unable to open %s due to errno:%d\n", text, errno); + } + } + + if (should_drop_privileges()) { + if (argv[2] != NULL && request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_ROOTCMD, argv[2])) { + // do nothing + D("sdb: executes root commands!!:%s\n", argv[2]); + } else { + if (getuid() != g_sdk_user_id && set_sdk_user_privileges(RESERVE_CAPABILITIES_AFTER_FORK) < 0) { + fprintf(stderr, "failed to set SDK user privileges\n"); + exit(-1); + } + } + } else { + set_root_privileges(); + } + redirect_and_exec(pts, cmd, argv, envp); + fprintf(stderr, "- exec '%s' failed: (errno:%d) -\n", + cmd, errno); + exit(-1); + } else { + // Don't set child's OOM adjustment to zero. + // Let the child do it itself, as sometimes the parent starts + // running before the child has a /proc/pid/oom_adj. + // """sdb: unable to open /proc/644/oom_adj""" seen in some logs. + return ptm; + } +} + /* receive the ptm from child, sdbd-user */ static ssize_t recv_fd(int fd, void *ptr, size_t nbytes, int *recvfd) { @@ -416,7 +510,7 @@ static ssize_t recv_fd(int fd, void *ptr, size_t nbytes, int *recvfd) return ret; } -int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[]) +int create_userprocess(const char *cmd, pid_t *pid, char * const argv[], char * const envp[]) { *pid = fork(); if(*pid < 0) { @@ -512,7 +606,7 @@ int create_subprocess(const char *cmd, pid_t *pid, char * const argv[], char * c } #endif /* !SDB_HOST */ -#define SHELL_COMMAND "/usr/sbin/sdbd-user" +#define USER_DAEMON_COMMAND "/usr/sbin/sdbd-user" #define LOGIN_COMMAND "/bin/login" #define SUPER_USER "root" #define LOGIN_CONFIG "/etc/login.defs" @@ -688,14 +782,14 @@ static int create_subproc_thread(const char *name, int lines, int columns) D("converted cmd : %s\n", new_cmd); char *args[] = { - SHELL_COMMAND, + USER_DAEMON_COMMAND, "-c", NULL, NULL, }; args[2] = new_cmd; - ret_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp); + ret_fd = create_userprocess(USER_DAEMON_COMMAND, &pid, (char * const*)args, (char * const*)envp); free(new_cmd); } else { // in case of shell interactively // Check the capability for interactive shell support. @@ -705,19 +799,19 @@ static int create_subproc_thread(const char *name, int lines, int columns) } char * const args[] = { - SHELL_COMMAND, + USER_DAEMON_COMMAND, "-", NULL, }; - ret_fd = create_subprocess(SHELL_COMMAND, &pid, (char * const*)args, (char * const*)envp); + ret_fd = create_userprocess(USER_DAEMON_COMMAND, &pid, (char * const*)args, (char * const*)envp); #if 0 // FIXME: should call login command instead of /bin/sh if (should_drop_privileges()) { char *args[] = { - SHELL_COMMAND, + USER_DAEMON_COMMAND, "-", NULL, }; - ret_fd = create_subprocess(SHELL_COMMAND, &pid, args, envp); + ret_fd = create_userprocess(USER_DAEMON_COMMAND, &pid, args, envp); } else { char *args[] = { LOGIN_COMMAND, -- 2.7.4 From 0844f3b6cf15407b577f6d5653302d6af6fdf874 Mon Sep 17 00:00:00 2001 From: Sooyoung Ha Date: Mon, 27 Mar 2017 15:03:08 +0900 Subject: [PATCH 14/16] package: update version (3.0.18) Change-Id: I43d8e8f049b7cb91838d4d48d52c91680a61b672 Signed-off-by: Sooyoung Ha --- packaging/sdbd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 7f6c4aa..824e475 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.17 +Version: 3.0.18 Release: 0 License: Apache-2.0 Summary: SDB daemon -- 2.7.4 From 29ad9904acb9d6ec0885721e8aa59e3f13794d5f Mon Sep 17 00:00:00 2001 From: Jinhyung Choi Date: Wed, 29 Mar 2017 14:31:23 +0900 Subject: [PATCH 15/16] appcmd: modify runapp command for watchapp type Change-Id: If92e6400b7e88c33ee088fe551127778b962df2e Signed-off-by: Jinhyung Choi --- src/default_plugin_appcmd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/default_plugin_appcmd.c b/src/default_plugin_appcmd.c index c929cf2..643fb77 100644 --- a/src/default_plugin_appcmd.c +++ b/src/default_plugin_appcmd.c @@ -128,7 +128,10 @@ static int appcmd_runapp_gen_shellcmd(appcmd_info* p_info) { D("args: appid=%s\n", appid); - snprintf(buf, len, "/usr/bin/app_launcher --start %s", appid); + snprintf(buf, len, "/usr/bin/pkginfo --app %s | grep component: | awk '{print $2}'" + " | while read var; do if [ $var = watchapp ]; then /usr/bin/app_launcher " + "--start org.tizen.widget_viewer_sdk widget_id %s; else /usr/bin/app_launcher " + "--start %s; fi; done", appid, appid, appid); return 0; } -- 2.7.4 From 12045bfedb7f8deaac7143fbf3a42e9188ecf538 Mon Sep 17 00:00:00 2001 From: Jinhyung Choi Date: Wed, 29 Mar 2017 14:48:46 +0900 Subject: [PATCH 16/16] package: update version (3.0.19) Change-Id: I996b447fb2a38c029c049ffd23f92230ee7f75fc Signed-off-by: Jinhyung Choi --- packaging/sdbd.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/sdbd.spec b/packaging/sdbd.spec index 824e475..5ec9380 100644 --- a/packaging/sdbd.spec +++ b/packaging/sdbd.spec @@ -2,7 +2,7 @@ Name: sdbd Summary: SDB daemon -Version: 3.0.18 +Version: 3.0.19 Release: 0 License: Apache-2.0 Summary: SDB daemon -- 2.7.4