service: change method of create_process function 11/120911/1
authorSooyoung Ha <yoosah.ha@samsung.com>
Fri, 24 Mar 2017 15:46:21 +0000 (00:46 +0900)
committerSooyoung Ha <yoosah.ha@samsung.com>
Fri, 24 Mar 2017 15:57:11 +0000 (00:57 +0900)
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 <yoosah.ha@samsung.com>
src/services.c

index f6c1df6..1daaa43 100644 (file)
@@ -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,