# include <sys/inotify.h>
# include "sdktools.h"
#endif
+#include <sys/socket.h>
+#include <sys/un.h>
#include "strutils.h"
#include "utils.h"
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")) {
}
#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;
- }
-
- if (smack_setlabel(devname, SDK_SHELL_LABEL_NAME, SMACK_LABEL_ACCESS) == -1) {
- D("unable to set sdk shell smack label %s due to (errno:%d)\n", SDK_SHELL_LABEL_NAME, 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 && 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) {
- fprintf(stderr, "failed to set SDK user privileges\n");
+ if (getuid() != g_sdk_user_id && set_sdk_user_privileges(RESERVE_CAPABILITIES_AFTER_FORK) < 0) {
+ 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)) {
// 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);
// 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,
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