Add routine to scan rules.conf file and move matching running tasks
in /proc/pid/* into configured control groups.

Without this adding control group after cgrulesengd has started
does not work correctly and processes running before cgrulesengd
is started are not managed.

This new routine is called at init time and also after inotify events
on control groups.

Signed-off-by: John Fastabend <john.r.fastab...@intel.com>
---

 include/libcgroup/tasks.h |    1 +
 src/api.c                 |   77 +++++++++++++++++++++++++++++++++++++++++++++
 src/daemon/cgrulesengd.c  |   75 +++++++++++++++++++++++++++++++++++++++++---
 src/libcgroup.map         |    1 +
 4 files changed, 149 insertions(+), 5 deletions(-)

diff --git a/include/libcgroup/tasks.h b/include/libcgroup/tasks.h
index fb728f4..120af69 100644
--- a/include/libcgroup/tasks.h
+++ b/include/libcgroup/tasks.h
@@ -107,6 +107,7 @@ int cgroup_reload_cached_rules(void);
  * @param fp Destination file, where the rules will be printed.
  */
 void cgroup_print_rules_config(FILE *fp);
+void cgroup_search_rules_config(void);
 
 /**
  * @}
diff --git a/src/api.c b/src/api.c
index 29de777..ebf53ee 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2837,6 +2837,83 @@ int cgroup_change_cgroup_path(const char *dest, pid_t 
pid,
        return ret;
 }
 
+static int cg_get_pid_from_flags(int uid, int gid, char *procname, int *pid)
+{
+       DIR *dir;
+       struct dirent *pid_dir = NULL;
+       char *path = "/proc/";
+       char pid_path[100];
+       char pid_name[100];
+       char buff[80];
+       int sgid = -1;
+       int suid = -1;
+       int spid = -1;
+       FILE *fd;
+
+       dir = opendir(path);
+       if (!dir)
+               return ECGOTHER;
+
+       while ((pid_dir = readdir(dir)) != NULL) {
+               snprintf(pid_path, sizeof(pid_path),
+                        "%s%s/status", path, pid_dir->d_name);
+               fd = fopen(pid_path, "r");
+               if (!fd)
+                       continue;
+               memset(pid_path, 0, sizeof(pid_path));
+               sgid = suid = -1;
+               while (fgets(buff, sizeof(buff), fd) != NULL) {
+                       sscanf(buff, "Name: %s", pid_name);
+                       sscanf(buff, "Gid: %i", &sgid);
+                       sscanf(buff, "Uid: %i", &suid);
+                       sscanf(buff, "Pid: %i", &spid);
+               }
+
+               if ((strncmp(procname, pid_name, sizeof(procname)) == 0) &&
+                   (gid == (int) CGRULE_WILD || gid == sgid) &&
+                   (uid == (int) CGRULE_WILD || uid == suid)) {
+                       closedir(dir);
+                       fclose(fd);
+                       *pid = spid;
+                       return 0;
+               }
+
+               fclose(fd);
+       }
+
+       closedir(dir);
+       return 1;
+}
+
+void cgroup_search_rules_config(void)
+{
+       struct cgroup_rule *itr = NULL;
+
+       pthread_rwlock_rdlock(&rl_lock);
+
+       if (!(rl.head)) {
+               pthread_rwlock_unlock(&rl_lock);
+               return;
+       }
+
+       itr = rl.head;
+       while (itr) {
+               int pid = 0;
+               int err = cg_get_pid_from_flags(itr->uid, itr->gid,
+                                               itr->procname, &pid);
+
+               if (!err) {
+                       pthread_rwlock_unlock(&rl_lock);
+                       cgroup_change_cgroup_flags(itr->uid, itr->gid,
+                                                  itr->procname, pid, 0);
+                       pthread_rwlock_rdlock(&rl_lock);
+               }
+               itr = itr->next;
+       }
+       pthread_rwlock_unlock(&rl_lock);
+}
+
+
 /**
  * Print the cached rules table.  This function should be called only after
  * first calling cgroup_parse_config(), but it will work with an empty rule
diff --git a/src/daemon/cgrulesengd.c b/src/daemon/cgrulesengd.c
index ff72965..763e893 100644
--- a/src/daemon/cgrulesengd.c
+++ b/src/daemon/cgrulesengd.c
@@ -56,6 +56,8 @@
 #include <linux/un.h>
 #include <pwd.h>
 #include <grp.h>
+#include <sys/inotify.h>
+#include <mntent.h>
 
 #define NUM_PER_REALLOCATIOM   (100)
 
@@ -496,6 +498,25 @@ static int cgre_handle_msg(struct cn_msg *cn_hdr)
        return ret;
 }
 
+static int cgre_receive_inotify_msg(int sk_inot)
+{
+       struct inotify_event *event;
+       char buf[BUFF_SIZE] = "";
+       int ret = 0;
+
+       ret = read(sk_inot, buf, sizeof(buf));
+       if (ret < 0)
+               return ret;
+
+       for (event = (struct inotify_event *) buf; ret > 0; event++) {
+               flog(LOG_DEBUG, "INOTIFY Event: %s", event->name);
+               ret -= (sizeof(*event) + event->len);
+       }
+
+       cgroup_search_rules_config();
+       return ret;
+}
+
 static int cgre_receive_netlink_msg(int sk_nl)
 {
        char buff[BUFF_SIZE];
@@ -590,7 +611,7 @@ close:
 
 static int cgre_create_netlink_socket_process_msg(void)
 {
-       int sk_nl = 0, sk_unix = 0, sk_max;
+       int sk_nl = 0, sk_unix = 0, sk_inot = 0, sk_inot_cg = 0, sk_max;
        struct sockaddr_nl my_nla;
        char buff[BUFF_SIZE];
        int rc = -1;
@@ -598,6 +619,9 @@ static int cgre_create_netlink_socket_process_msg(void)
        struct cn_msg *cn_hdr;
        enum proc_cn_mcast_op *mcop_msg;
        struct sockaddr_un saddr;
+       struct mntent *ent, temp_ent;
+       char mntent_buffer[4 * FILENAME_MAX];
+       FILE *proc_mount;
        fd_set fds, readfds;
        sigset_t sigset;
 
@@ -690,13 +714,45 @@ static int cgre_create_netlink_socket_process_msg(void)
                goto close_and_exit;
        }
 
+       /* inotify socket listen for controller change events */
+       sk_inot = inotify_init();
+       if (sk_inot < 0) {
+               cgroup_dbg("Error intializing inotify subsystem\n");
+               goto close_and_exit;
+       }
+
+       proc_mount = fopen("/proc/mounts", "re");
+       if (!proc_mount) {
+               cgroup_dbg("Error proc mount open failed\n");
+               goto close_and_exit;
+       }
+
+       while ((ent = getmntent_r(proc_mount, &temp_ent,
+                                 mntent_buffer,
+                                 sizeof(mntent_buffer))) != NULL) {
+               uint32_t mask = IN_CREATE | IN_DELETE;
+
+               if (strcmp(ent->mnt_fsname, "cgroup_root") &&
+                   strcmp(ent->mnt_type, "cgroup"))
+                       continue;
+
+               flog(LOG_DEBUG, "Mount watch %s@%s",
+                    ent->mnt_fsname, ent->mnt_dir);
+
+               sk_inot_cg = inotify_add_watch(sk_inot, ent->mnt_dir, mask);
+               if (sk_inot_cg < 0) {
+                       perror("Error adding watch");
+                       goto close_and_exit;
+               }
+       }
+
        FD_ZERO(&readfds);
        FD_SET(sk_nl, &readfds);
        FD_SET(sk_unix, &readfds);
-       if (sk_nl < sk_unix)
-               sk_max = sk_unix;
-       else
-               sk_max = sk_nl;
+       FD_SET(sk_inot, &readfds);
+
+       sk_max = max(sk_nl, sk_unix);
+       sk_max = max(sk_max, sk_inot);
 
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGUSR2);
@@ -719,6 +775,8 @@ static int cgre_create_netlink_socket_process_msg(void)
                }
                if (FD_ISSET(sk_unix, &fds))
                        cgre_receive_unix_domain_msg(sk_unix);
+               if (FD_ISSET(sk_inot, &fds))
+                       cgre_receive_inotify_msg(sk_inot);
        }
 
 close_and_exit:
@@ -726,6 +784,10 @@ close_and_exit:
                close(sk_nl);
        if (sk_unix > 0)
                close(sk_unix);
+       if (sk_inot_cg > 0)
+               close(sk_inot_cg);
+       if (sk_inot > 0)
+               close(sk_inot);
        return rc;
 }
 
@@ -1130,6 +1192,9 @@ int main(int argc, char *argv[])
        if (logfile && loglevel >= LOG_INFO)
                cgroup_print_rules_config(logfile);
 
+       /* Scan for running daemons and applications with rules */
+       cgroup_search_rules_config();
+
        flog(LOG_NOTICE, "Started the CGroup Rules Engine Daemon.");
 
        /* We loop endlesly in this function, unless we encounter an error. */
diff --git a/src/libcgroup.map b/src/libcgroup.map
index e73dd6e..fdf312e 100644
--- a/src/libcgroup.map
+++ b/src/libcgroup.map
@@ -33,6 +33,7 @@ global:
        cgroup_set_value_bool;
        cgroup_change_cgroup_uid_gid_flags;
        cgroup_print_rules_config;
+       cgroup_search_rules_config;
        cgroup_reload_cached_rules;
        cgroup_init_rules_cache;
        cgroup_get_current_controller_path;


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to