diff options
author | Jan Safranek <jsafrane@redhat.com> | 2009-05-26 15:09:03 +0200 |
---|---|---|
committer | Jan Safranek <jsafrane@redhat.com> | 2009-05-26 15:09:03 +0200 |
commit | 37f11368ff2aca9ff736bd569ca58f48623c200b (patch) | |
tree | 5a705a23c32b0acc4bb37d1913db8fcc3a309997 | |
parent | 9d3b7b6c8b8855e6bd63aecb9872ef7022394d4f (diff) | |
download | libcg-37f11368ff2aca9ff736bd569ca58f48623c200b.tar.gz libcg-37f11368ff2aca9ff736bd569ca58f48623c200b.tar.xz libcg-37f11368ff2aca9ff736bd569ca58f48623c200b.zip |
Hi,
This patch adds the key "process name" to find a matching rule.
By this patch, cgroup_change_cgroup_uid_gid_flags() gets a process
name by the parameter "pid" internally and uses it to find a matching
rule.
Thanks
Ken'ichi Ohmichi
Signed-off-by: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
-rw-r--r-- | src/api.c | 60 |
1 files changed, 47 insertions, 13 deletions
@@ -286,10 +286,12 @@ static char *cg_skip_unused_charactors_in_rule(char *rule) * @param cache True to cache rules, else false * @param muid If cache is false, the UID to match against * @param mgid If cache is false, the GID to match against + * @param mprocname If cache is false, the process name to match against * @return 0 on success, -1 if no cache and match found, > 0 on error. * TODO: Make this function thread safe! */ -static int cgroup_parse_rules(bool cache, uid_t muid, gid_t mgid) +static int cgroup_parse_rules(bool cache, uid_t muid, gid_t mgid, + char *mprocname) { /* File descriptor for the configuration file */ FILE *fp = NULL; @@ -486,8 +488,20 @@ static int cgroup_parse_rules(bool cache, uid_t muid, gid_t mgid) matched = true; } - if (!cache && !matched) - continue; + if (!cache) { + if (!matched) + continue; + if (len_procname) { + /* + * If there is a rule based on process name, + * it should be matched with mprocname. + */ + if (!mprocname) + continue; + if (strncmp(mprocname, procname, len_procname)) + continue; + } + } /* * Now, we're either caching rules or we found a match. Either @@ -1805,11 +1819,12 @@ static int cg_prepare_cgroup(struct cgroup *cgroup, pid_t pid, * This function may NOT be thread safe. * @param uid The UID to match * @param gid The GID to match + * @param procname The process name to match * @return Pointer to the first matching rule, or NULL if no match * TODO: Determine thread-safeness and fix if not safe. */ -static struct cgroup_rule *cgroup_find_matching_rule_uid_gid(const uid_t uid, - const gid_t gid) +static struct cgroup_rule *cgroup_find_matching_rule(const uid_t uid, + const gid_t gid, const char *procname) { /* Return value */ struct cgroup_rule *ret = rl.head; @@ -1827,20 +1842,21 @@ static struct cgroup_rule *cgroup_find_matching_rule_uid_gid(const uid_t uid, int i = 0; pthread_rwlock_wrlock(&rl_lock); +retry: while (ret) { /* The wildcard rule always matches. */ if ((ret->uid == CGRULE_WILD) && (ret->gid == CGRULE_WILD)) { - goto finished; + goto found_uid_gid_rule; } /* This is the simple case of the UID matching. */ if (ret->uid == uid) { - goto finished; + goto found_uid_gid_rule; } /* This is the simple case of the GID matching. */ if (ret->gid == gid) { - goto finished; + goto found_uid_gid_rule; } /* If this is a group rule, the UID might be a member. */ @@ -1861,7 +1877,7 @@ static struct cgroup_rule *cgroup_find_matching_rule_uid_gid(const uid_t uid, /* If UID is a member of group, we matched. */ for (i = 0; grp->gr_mem[i]; i++) { if (!(strcmp(usr->pw_name, grp->gr_mem[i]))) - goto finished; + goto found_uid_gid_rule; } } @@ -1872,6 +1888,16 @@ static struct cgroup_rule *cgroup_find_matching_rule_uid_gid(const uid_t uid, /* If we get here, no rules matched. */ ret = NULL; +found_uid_gid_rule: + if (ret && procname) { + if (!ret->procname) + /* If no process name in a rule, that means wildcard */ + goto finished; + if (!strcmp(ret->procname, procname)) + goto finished; + ret = ret->next; + goto retry; + } finished: pthread_rwlock_unlock(&rl_lock); return ret; @@ -1900,6 +1926,9 @@ int cgroup_change_cgroup_uid_gid_flags(const uid_t uid, const gid_t gid, /* Temporary pointer to a rule */ struct cgroup_rule *tmp = NULL; + /* Buffer of process name */ + char procname[TASK_COMM_LEN] = { '\0' }; + /* Return codes */ int ret = 0; @@ -1909,6 +1938,10 @@ int cgroup_change_cgroup_uid_gid_flags(const uid_t uid, const gid_t gid, ret = ECGROUPNOTINITIALIZED; goto finished; } + ret = cgroup_get_procdata_from_status(pid, NULL, NULL, + procname, sizeof(procname)); + if (ret) + goto finished; /* * If the user did not ask for cached rules, we must parse the @@ -1917,7 +1950,7 @@ int cgroup_change_cgroup_uid_gid_flags(const uid_t uid, const gid_t gid, */ if (!(flags & CGFLAG_USECACHE)) { cgroup_dbg("Not using cached rules for PID %d.\n", pid); - ret = cgroup_parse_rules(false, uid, gid); + ret = cgroup_parse_rules(false, uid, gid, procname); /* The configuration file has an error! We must exit now. */ if (ret != -1 && ret != 0) { @@ -1937,7 +1970,7 @@ int cgroup_change_cgroup_uid_gid_flags(const uid_t uid, const gid_t gid, tmp = trl.head; } else { /* Find the first matching rule in the cached list. */ - tmp = cgroup_find_matching_rule_uid_gid(uid, gid); + tmp = cgroup_find_matching_rule(uid, gid, procname); if (!tmp) { cgroup_dbg("No rule found to match PID: %d, UID: %d, " "GID: %d\n", pid, uid, gid); @@ -2084,7 +2117,8 @@ int cgroup_reload_cached_rules() int ret = 0; cgroup_dbg("Reloading cached rules from %s.\n", CGRULES_CONF_FILE); - if ((ret = cgroup_parse_rules(true, CGRULE_INVALID, CGRULE_INVALID))) { + ret = cgroup_parse_rules(true, CGRULE_INVALID, CGRULE_INVALID, NULL); + if (ret) { cgroup_dbg("Error parsing configuration file \"%s\": %d.\n", CGRULES_CONF_FILE, ret); ret = ECGROUPPARSEFAIL; @@ -2109,7 +2143,7 @@ int cgroup_init_rules_cache() int ret = 0; /* Attempt to read the configuration file and cache the rules. */ - ret = cgroup_parse_rules(true, CGRULE_INVALID, CGRULE_INVALID); + ret = cgroup_parse_rules(true, CGRULE_INVALID, CGRULE_INVALID, NULL); if (ret) { cgroup_dbg("Could not initialize rule cache, error was: %d\n", ret); |