From: Kamalesh Babulal Date: Tue, 21 Jan 2025 08:10:27 +0000 (+0530) Subject: cgrules: add support for process/dest cgroups with spaces X-Git-Tag: v3.2.0~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=914b919d007611912d714f7935111d9275494f8e;p=thirdparty%2Flibcgroup.git cgrules: add support for process/dest cgroups with spaces In a cgrules rule, allow the process names and the destination cgroups with spaces and other allowed special characters. Reported-by: @LinuxOnTheDesktop (github username) Fixes: https://github.com/libcgroup/libcgroup/issues/462 Signed-off-by: Kamalesh Babulal Signed-off-by: Tom Hromatka TJH: slight logic changes and add gunit support --- diff --git a/src/api.c b/src/api.c index 6df516fa..7ff095e7 100644 --- a/src/api.c +++ b/src/api.c @@ -554,6 +554,71 @@ STATIC int cgroup_parse_rules_options(char *options, struct cgroup_rule * const return ret; } + +STATIC int get_next_rule_field(char *rule, char *field, size_t field_len, bool expect_quotes) +{ + char *quote_start = NULL, *quote_end = NULL; + char *tmp, *_rule = rule; + int len = 0; + + if (!rule || !field) + return ECGINVAL; + + /* trim the leading whitespace */ + while (*rule == ' ' || *rule == '\t') + rule++; + + tmp = rule; + + while (*rule != ' ' && *rule != '\t' && *rule != '\n' && *rule != '\0') { + if (*rule == '"') { + quote_start = rule; + rule++; + break; + } + rule++; + } + + if (quote_start) { + if (!expect_quotes) + return ECGINVAL; + + while (*rule != '"' && *rule != '\n' && *rule != '\0') + rule++; + + /* there should be a ending quote */ + if (*rule != '"') + return ECGINVAL; + + quote_end = rule; + } + + if (quote_end) { + /* copy until the ending quotes */ + len = quote_end - quote_start - 1; + if (len >= field_len) + return ECGINVAL; + + strncpy(field, quote_start + 1, len); + field[len] = '\0'; + } else { + len = rule - tmp; + if (len >= field_len) + return ECGINVAL; + + strncpy(field, tmp, len); + field[len] = '\0'; + } + + len = (rule - _rule); + + /* count until the ending quotes */ + if (quote_start) + len += 1; + + return len; +} + /** * Parse the configuration file that maps UID/GIDs to cgroups. If ever the * configuration file is modified, applications should call this function to @@ -677,15 +742,33 @@ static int cgroup_parse_rules_file(char *filename, bool cache, uid_t muid, gid_t * there's an error in the configuration file. */ skipped = false; - i = sscanf(itr, "%s%s%s%s", key, controllers, destination, options); - if (i < 3) { + + ret = get_next_rule_field(itr, key, CGRP_RULE_MAXKEY, true); + if (!ret) { + cgroup_err("failed to parse configuration file on line %d\n", linenum); + goto parsefail; + } + + itr += ret; + ret = get_next_rule_field(itr, controllers, CG_CONTROLLER_MAX, false); + if (!ret) { + cgroup_err("failed to parse configuration file on line %d\n", linenum); + goto parsefail; + } + + itr += ret; + ret = get_next_rule_field(itr, destination, FILENAME_MAX, true); + if (!ret) { cgroup_err("failed to parse configuration file on line %d\n", linenum); goto parsefail; - } else if (i == 3) { + } + + itr += ret; + ret = get_next_rule_field(itr, options, CG_OPTIONS_MAX, false); + if (!ret) has_options = false; - } else if (i == 4) { + else has_options = true; - } procname = strchr(key, ':'); if (procname) { diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h index 48dbf1c0..bb5c2213 100644 --- a/src/libcgroup-internal.h +++ b/src/libcgroup-internal.h @@ -423,6 +423,7 @@ int cgroup_chown_chmod_tasks(const char * const cg_path, uid_t uid, gid_t gid, m int cgroupv2_subtree_control(const char *path, const char *ctrl_name, bool enable); int cgroupv2_get_subtree_control(const char *path, const char *ctrl_name, bool * const enabled); int cgroupv2_controller_enabled(const char * const cg_name, const char * const ctrl_name); +int get_next_rule_field(char *rule, char *field, size_t field_len, bool expect_quotes); #endif /* UNIT_TEST */