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

Reply via email to