############################# 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)
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()
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
User=sdk
Group=sdk
Type=forking
-#location of SDBD log file
Environment=DISPLAY=:0
PIDFile=/tmp/.sdbd.pid
RemainAfterExit=yes
# include <sys/inotify.h>
# include "sdktools.h"
#endif
+#include <sys/socket.h>
+#include <sys/un.h>
#include "strutils.h"
#include "utils.h"
}
#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"
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)) {
--- /dev/null
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#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;
+ }
+}