]> git.ipfire.org Git - thirdparty/libcgroup.git/commitdiff
Set cgrulesengd socket owner
authorJan Safranek <jsafrane@redhat.com>
Mon, 15 Nov 2010 13:59:44 +0000 (14:59 +0100)
committerDhaval Giani <dhaval.giani@gmail.com>
Tue, 16 Nov 2010 15:39:16 +0000 (16:39 +0100)
Currently, cgexec has suid flag and runs as root because it needs to
communicate with cgrulesengd using /var/run/cgred.socket. This is generally
frowned upon, so let's add few options to cgrulesengd to set the socket
owner to someone else - cgexec does not need to run as powerful root, but
as some new harmless user or group.

Signed-off-by: Jan Safranek <jsafrane@redhat.com>
Signed-off-by: Dhaval Giani <dhaval.giani@gmail.com>
doc/man/cgrulesengd.8
src/daemon/cgrulesengd.c
src/tools/cgexec.c

index 2e4f60cb9bb7f29cf8a2b749ef941c20faa9c8bd..10d1d096744fc1f2a3e38b610fd88c8b9771ba63 100644 (file)
@@ -16,6 +16,9 @@ the appropriate control group.
 The list of rules is read during the daemon startup and are cached in daemon's memory.
 The daemon reloads the list of rules when it receives SIGUSR2 signal.
 
+The daemon opens a standard unix socket to receive 'sticky' requests from
+cgexec tool.
+
 .SH OPTIONS
 .TP
 .B -h|--help
@@ -47,7 +50,11 @@ Disable logging.
 .B -d|--debug
 Equivalent to '-nvvf -', i.e. don't fork the daemon, display all log messages and
 write them to the standard output.
-
+.TP
+.B -u <user>|--socket-user=<user>
+.B -g <group>|--socket-group=<group>
+Set owner of cgrulesengd socket. It assumes that cgexec tool runs with proper
+suid permissions so it can write to the socket when cgexec --sticky is used.
 .SH FILES
 .LP
 .PD .1v
index dc3febce6d5f033c57357863882f9f610bf2ae41..69165bfee4004afa2663fc42302e9b5e40e58071 100644 (file)
@@ -54,6 +54,8 @@
 #include <linux/connector.h>
 #include <linux/cn_proc.h>
 #include <linux/un.h>
+#include <pwd.h>
+#include <grp.h>
 
 #define NUM_PER_REALLOCATIOM   (100)
 
@@ -66,6 +68,12 @@ int logfacility;
 /* Current log level */
 int loglevel;
 
+/* Owner of the socket, -1 means no change */
+uid_t socket_user = -1;
+
+/* Owner of the socket, -1 means no change */
+gid_t socket_group = -1;
+
 /**
  * Prints the usage information for this program and, optionally, an error
  * message.  This function uses vfprintf.
@@ -94,6 +102,10 @@ static void usage(FILE* fd, const char* msg, ...)
                "    -n           | --nodaemom          don't fork daemon\n"
                "    -d           | --debug             same as -v -v -n -f -\n"
                "    -Q           | --nolog             disable logging\n"
+               "    -u <user>    | --socket-user=<user> set "
+                       CGRULE_CGRED_SOCKET_PATH " socket user\n"
+               "    -g <group>   | --socket-group=<group> set "
+                       CGRULE_CGRED_SOCKET_PATH " socket group\n"
                "    -h           | --help              show this help\n\n"
                );
        va_end(ap);
@@ -650,6 +662,23 @@ static int cgre_create_netlink_socket_process_msg(void)
                cgroup_dbg("listening sk_unix error: %s\n", strerror(errno));
                goto close_and_exit;
        }
+
+       /* change the owner */
+       if (chown(CGRULE_CGRED_SOCKET_PATH, socket_user, socket_group) < 0) {
+               cgroup_dbg("Error changing socket owner: %s\n",
+                               strerror(errno));
+               goto close_and_exit;
+       }
+       cgroup_dbg("Socket %s owner successfully set to %d:%d\n",
+                       CGRULE_CGRED_SOCKET_PATH, (int) socket_user,
+                       (int) socket_group);
+
+       if (chmod(CGRULE_CGRED_SOCKET_PATH, 0660) < 0) {
+               cgroup_dbg("Error changing socket owner: %s\n",
+                               strerror(errno));
+               goto close_and_exit;
+       }
+
        FD_ZERO(&readfds);
        FD_SET(sk_nl, &readfds);
        FD_SET(sk_unix, &readfds);
@@ -927,8 +956,11 @@ int main(int argc, char *argv[])
        /* Return codes */
        int ret = 0;
 
+       struct passwd *pw;
+       struct group *gr;
+
        /* Command line arguments */
-       const char *short_options = "hvqf:s::ndQ";
+       const char *short_options = "hvqf:s::ndQu:g:";
        struct option long_options[] = {
                {"help", no_argument, NULL, 'h'},
                {"verbose", no_argument, NULL, 'v'},
@@ -938,6 +970,8 @@ int main(int argc, char *argv[])
                {"nodaemon", no_argument, NULL, 'n'},
                {"debug", no_argument, NULL, 'd'},
                {"nolog", no_argument, NULL, 'Q'},
+               {"socket-user", required_argument, NULL, 'u'},
+               {"socket-group", required_argument, NULL, 'g'},
                {NULL, 0, NULL, 0}
        };
 
@@ -1003,7 +1037,28 @@ int main(int argc, char *argv[])
                        verbosity = 4;
                        logp = "-";
                        break;
-
+               case 'u': /* --socket-user */
+                       pw = getpwnam(optarg);
+                       if (pw == NULL) {
+                               usage(stderr, "Cannot find user %s", optarg);
+                               ret = 3;
+                               goto finished;
+                       }
+                       socket_user = pw->pw_uid;
+                       cgroup_dbg("Using socket user %s id %d\n",
+                                       optarg, (int)socket_user);
+                       break;
+               case 'g': /* --socket-group */
+                       gr = getgrnam(optarg);
+                       if (gr == NULL) {
+                               usage(stderr, "Cannot find group %s", optarg);
+                               ret = 3;
+                               goto finished;
+                       }
+                       socket_group = gr->gr_gid;
+                       cgroup_dbg("Using socket group %s id %d\n",
+                                       optarg, (int)socket_group);
+                       break;
                default:
                        usage(stderr, "");
                        ret = 2;
index 07af199061b50ac7ae273a351990101b49b71f5d..7552fd98578c3030523bca7755bfd3f2319bde99 100644 (file)
@@ -92,6 +92,11 @@ int main(int argc, char *argv[])
                return ret;
        }
 
+       /* Just for debugging purposes. */
+       uid = geteuid();
+       gid = getegid();
+       cgroup_dbg("My euid and eguid is: %d,%d\n", (int) uid, (int) gid);
+
        uid = getuid();
        gid = getgid();
        pid = getpid();
@@ -105,13 +110,17 @@ int main(int argc, char *argv[])
        /*
         * 'cgexec' command file needs the root privilege for executing
         * a cgroup_register_unchanged_process() by using unix domain
-        * socket, and an euid should be changed to the executing user
+        * socket, and an euid/egid should be changed to the executing user
         * from a root user.
         */
        if (seteuid(uid)) {
                fprintf(stderr, "%s", strerror(errno));
                return -1;
        }
+       if (setegid(gid)) {
+               fprintf(stderr, "%s", strerror(errno));
+               return -1;
+       }
        if (cg_specified) {
                /*
                 * User has specified the list of control group and