summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Safranek <jsafrane@redhat.com>2009-05-26 15:09:03 +0200
committerJan Safranek <jsafrane@redhat.com>2009-05-26 15:09:03 +0200
commit37f11368ff2aca9ff736bd569ca58f48623c200b (patch)
tree5a705a23c32b0acc4bb37d1913db8fcc3a309997
parent9d3b7b6c8b8855e6bd63aecb9872ef7022394d4f (diff)
downloadlibcg-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.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/src/api.c b/src/api.c
index 3e063cb..ba39280 100644
--- a/src/api.c
+++ b/src/api.c
@@ -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);