Ken'ichi Ohmichi wrote:
> 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 <[email protected]>
> ---
> src/api.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------------
> 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;
Why not strcmp? procname can be "/usr/bin/at" and mprocname e.g.
"/usr/bin/attr"...
> + }
> + }
>
> /*
> * 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;
It is extremely ugly to leave the loop to compare procname and enter it
again if it does not match! I admit the original code was not much
better, all these gotos and labels... What's wrong with good old break?
> + }
> 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);
>
> ------------------------------------------------------------------------------
> Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
> is a gathering of tech-side developers & brand creativity professionals. Meet
> the minds behind Google Creative Lab, Visual Complexity, Processing, &
> iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian
> Group, R/GA, & Big Spaceship. http://www.creativitycat.com
> _______________________________________________
> Libcg-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/libcg-devel
------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, &
iPhoneDevCamp as they present alongside digital heavyweights like Barbarian
Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel