From: Jan Safranek Date: Mon, 15 Nov 2010 13:59:44 +0000 (+0100) Subject: Set cgrulesengd socket owner X-Git-Tag: v0.37~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8567c337f1dfb7d8f95fabc69a7fb3c3fc352480;p=thirdparty%2Flibcgroup.git Set cgrulesengd socket owner 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 Signed-off-by: Dhaval Giani --- diff --git a/doc/man/cgrulesengd.8 b/doc/man/cgrulesengd.8 index 2e4f60cb..10d1d096 100644 --- a/doc/man/cgrulesengd.8 +++ b/doc/man/cgrulesengd.8 @@ -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 |--socket-user= +.B -g |--socket-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 diff --git a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c index dc3febce..69165bfe 100644 --- a/src/daemon/cgrulesengd.c +++ b/src/daemon/cgrulesengd.c @@ -54,6 +54,8 @@ #include #include #include +#include +#include #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 | --socket-user= set " + CGRULE_CGRED_SOCKET_PATH " socket user\n" + " -g | --socket-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; diff --git a/src/tools/cgexec.c b/src/tools/cgexec.c index 07af1990..7552fd98 100644 --- a/src/tools/cgexec.c +++ b/src/tools/cgexec.c @@ -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