From 0d1ce1e7dfa5cdd30948bee1d3b6c096bf37e91a Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 3 Nov 2020 19:58:37 -0500 Subject: [PATCH] import libselinux-2.9-4.el8_3 --- ...iminate-use-of-security_compute_user.patch | 354 ++++++++++++++++++ SPECS/libselinux.spec | 6 +- 2 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0009-libselinux-Eliminate-use-of-security_compute_user.patch diff --git a/SOURCES/0009-libselinux-Eliminate-use-of-security_compute_user.patch b/SOURCES/0009-libselinux-Eliminate-use-of-security_compute_user.patch new file mode 100644 index 0000000..68085cf --- /dev/null +++ b/SOURCES/0009-libselinux-Eliminate-use-of-security_compute_user.patch @@ -0,0 +1,354 @@ +From bfee1a3131580a7b9d8a7366764b8e78d99a9f1b Mon Sep 17 00:00:00 2001 +From: Petr Lautrbach +Date: Mon, 17 Feb 2020 21:47:35 +0100 +Subject: [PATCH] libselinux: Eliminate use of security_compute_user() + +get_ordered_context_list() code used to ask the kernel to compute the complete +set of reachable contexts using /sys/fs/selinux/user aka +security_compute_user(). This set can be so huge so that it doesn't fit into a +kernel page and security_compute_user() fails. Even if it doesn't fail, +get_ordered_context_list() throws away the vast majority of the returned +contexts because they don't match anything in +/etc/selinux/targeted/contexts/default_contexts or +/etc/selinux/targeted/contexts/users/ + +get_ordered_context_list() is rewritten to compute set of contexts based on +/etc/selinux/targeted/contexts/users/ and +/etc/selinux/targeted/contexts/default_contexts files and to return only valid +contexts, using security_check_context(), from this set. + +Fixes: https://github.com/SELinuxProject/selinux/issues/28 + +Signed-off-by: Petr Lautrbach +--- + libselinux/src/get_context_list.c | 212 +++++++++++++----------------- + 1 file changed, 93 insertions(+), 119 deletions(-) + +diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c +index 689e4658..26d7b3b9 100644 +--- a/libselinux/src/get_context_list.c ++++ b/libselinux/src/get_context_list.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -114,64 +115,41 @@ int get_default_context(const char *user, + return 0; + } + +-static int find_partialcon(char ** list, +- unsigned int nreach, char *part) ++static int is_in_reachable(char **reachable, const char *usercon_str) + { +- const char *conrole, *contype; +- char *partrole, *parttype, *ptr; +- context_t con; +- unsigned int i; ++ if (!reachable) ++ return 0; + +- partrole = part; +- ptr = part; +- while (*ptr && !isspace(*ptr) && *ptr != ':') +- ptr++; +- if (*ptr != ':') +- return -1; +- *ptr++ = 0; +- parttype = ptr; +- while (*ptr && !isspace(*ptr) && *ptr != ':') +- ptr++; +- *ptr = 0; +- +- for (i = 0; i < nreach; i++) { +- con = context_new(list[i]); +- if (!con) +- return -1; +- conrole = context_role_get(con); +- contype = context_type_get(con); +- if (!conrole || !contype) { +- context_free(con); +- return -1; +- } +- if (!strcmp(conrole, partrole) && !strcmp(contype, parttype)) { +- context_free(con); +- return i; ++ for (; *reachable != NULL; reachable++) { ++ if (strcmp(*reachable, usercon_str) == 0) { ++ return 1; + } +- context_free(con); + } +- +- return -1; ++ return 0; + } + +-static int get_context_order(FILE * fp, ++static int get_context_user(FILE * fp, + char * fromcon, +- char ** reachable, +- unsigned int nreach, +- unsigned int *ordering, unsigned int *nordered) ++ const char * user, ++ char ***reachable, ++ unsigned int *nreachable) + { + char *start, *end = NULL; + char *line = NULL; +- size_t line_len = 0; ++ size_t line_len = 0, usercon_len; ++ size_t user_len = strlen(user); + ssize_t len; + int found = 0; +- const char *fromrole, *fromtype; ++ const char *fromrole, *fromtype, *fromlevel; + char *linerole, *linetype; +- unsigned int i; ++ char **new_reachable = NULL; ++ char *usercon_str; + context_t con; ++ context_t usercon; ++ + int rc; + +- errno = -EINVAL; ++ errno = EINVAL; + + /* Extract the role and type of the fromcon for matching. + User identity and MLS range can be variable. */ +@@ -180,6 +158,7 @@ static int get_context_order(FILE * fp, + return -1; + fromrole = context_role_get(con); + fromtype = context_type_get(con); ++ fromlevel = context_range_get(con); + if (!fromrole || !fromtype) { + context_free(con); + return -1; +@@ -243,23 +222,75 @@ static int get_context_order(FILE * fp, + if (*end) + *end++ = 0; + +- /* Check for a match in the reachable list. */ +- rc = find_partialcon(reachable, nreach, start); +- if (rc < 0) { +- /* No match, skip it. */ ++ /* Check whether a new context is valid */ ++ if (SIZE_MAX - user_len < strlen(start) + 2) { ++ fprintf(stderr, "%s: one of partial contexts is too big\n", __FUNCTION__); ++ errno = EINVAL; ++ rc = -1; ++ goto out; ++ } ++ usercon_len = user_len + strlen(start) + 2; ++ usercon_str = malloc(usercon_len); ++ if (!usercon_str) { ++ rc = -1; ++ goto out; ++ } ++ ++ /* set range from fromcon in the new usercon */ ++ snprintf(usercon_str, usercon_len, "%s:%s", user, start); ++ usercon = context_new(usercon_str); ++ if (!usercon) { ++ if (errno != EINVAL) { ++ free(usercon_str); ++ rc = -1; ++ goto out; ++ } ++ fprintf(stderr, ++ "%s: can't create a context from %s, skipping\n", ++ __FUNCTION__, usercon_str); ++ free(usercon_str); + start = end; + continue; + } ++ free(usercon_str); ++ if (context_range_set(usercon, fromlevel) != 0) { ++ context_free(usercon); ++ rc = -1; ++ goto out; ++ } ++ usercon_str = context_str(usercon); ++ if (!usercon_str) { ++ context_free(usercon); ++ rc = -1; ++ goto out; ++ } + +- /* If a match is found and the entry is not already ordered +- (e.g. due to prior match in prior config file), then set +- the ordering for it. */ +- i = rc; +- if (ordering[i] == nreach) +- ordering[i] = (*nordered)++; ++ /* check whether usercon is already in reachable */ ++ if (is_in_reachable(*reachable, usercon_str)) { ++ context_free(usercon); ++ start = end; ++ continue; ++ } ++ if (security_check_context(usercon_str) == 0) { ++ new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *)); ++ if (!new_reachable) { ++ context_free(usercon); ++ rc = -1; ++ goto out; ++ } ++ *reachable = new_reachable; ++ new_reachable[*nreachable] = strdup(usercon_str); ++ if (new_reachable[*nreachable] == NULL) { ++ context_free(usercon); ++ rc = -1; ++ goto out; ++ } ++ new_reachable[*nreachable + 1] = 0; ++ *nreachable += 1; ++ } ++ context_free(usercon); + start = end; + } +- + rc = 0; + + out: +@@ -313,21 +344,6 @@ static int get_failsafe_context(const char *user, char ** newcon) + return 0; + } + +-struct context_order { +- char * con; +- unsigned int order; +-}; +- +-static int order_compare(const void *A, const void *B) +-{ +- const struct context_order *c1 = A, *c2 = B; +- if (c1->order < c2->order) +- return -1; +- else if (c1->order > c2->order) +- return 1; +- return strcmp(c1->con, c2->con); +-} +- + int get_ordered_context_list_with_level(const char *user, + const char *level, + char * fromcon, +@@ -395,11 +411,8 @@ int get_ordered_context_list(const char *user, + char *** list) + { + char **reachable = NULL; +- unsigned int *ordering = NULL; +- struct context_order *co = NULL; +- char **ptr; + int rc = 0; +- unsigned int nreach = 0, nordered = 0, freefrom = 0, i; ++ unsigned nreachable = 0, freefrom = 0; + FILE *fp; + char *fname = NULL; + size_t fname_len; +@@ -413,23 +426,6 @@ int get_ordered_context_list(const char *user, + freefrom = 1; + } + +- /* Determine the set of reachable contexts for the user. */ +- rc = security_compute_user(fromcon, user, &reachable); +- if (rc < 0) +- goto failsafe; +- nreach = 0; +- for (ptr = reachable; *ptr; ptr++) +- nreach++; +- if (!nreach) +- goto failsafe; +- +- /* Initialize ordering array. */ +- ordering = malloc(nreach * sizeof(unsigned int)); +- if (!ordering) +- goto failsafe; +- for (i = 0; i < nreach; i++) +- ordering[i] = nreach; +- + /* Determine the ordering to apply from the optional per-user config + and from the global config. */ + fname_len = strlen(user_contexts_path) + strlen(user) + 2; +@@ -440,8 +436,8 @@ int get_ordered_context_list(const char *user, + fp = fopen(fname, "re"); + if (fp) { + __fsetlocking(fp, FSETLOCKING_BYCALLER); +- rc = get_context_order(fp, fromcon, reachable, nreach, ordering, +- &nordered); ++ rc = get_context_user(fp, fromcon, user, &reachable, &nreachable); ++ + fclose(fp); + if (rc < 0 && errno != ENOENT) { + fprintf(stderr, +@@ -454,8 +450,7 @@ int get_ordered_context_list(const char *user, + fp = fopen(selinux_default_context_path(), "re"); + if (fp) { + __fsetlocking(fp, FSETLOCKING_BYCALLER); +- rc = get_context_order(fp, fromcon, reachable, nreach, ordering, +- &nordered); ++ rc = get_context_user(fp, fromcon, user, &reachable, &nreachable); + fclose(fp); + if (rc < 0 && errno != ENOENT) { + fprintf(stderr, +@@ -463,40 +458,19 @@ int get_ordered_context_list(const char *user, + __FUNCTION__, selinux_default_context_path()); + /* Fall through */ + } +- rc = 0; + } + +- if (!nordered) ++ if (!nreachable) + goto failsafe; + +- /* Apply the ordering. */ +- co = malloc(nreach * sizeof(struct context_order)); +- if (!co) +- goto failsafe; +- for (i = 0; i < nreach; i++) { +- co[i].con = reachable[i]; +- co[i].order = ordering[i]; +- } +- qsort(co, nreach, sizeof(struct context_order), order_compare); +- for (i = 0; i < nreach; i++) +- reachable[i] = co[i].con; +- free(co); +- +- /* Only report the ordered entries to the caller. */ +- if (nordered <= nreach) { +- for (i = nordered; i < nreach; i++) +- free(reachable[i]); +- reachable[nordered] = NULL; +- rc = nordered; +- } +- + out: +- if (rc > 0) ++ if (nreachable > 0) { + *list = reachable; ++ rc = nreachable; ++ } + else + freeconary(reachable); + +- free(ordering); + if (freefrom) + freecon(fromcon); + +@@ -519,7 +493,7 @@ int get_ordered_context_list(const char *user, + reachable = NULL; + goto out; + } +- rc = 1; /* one context in the list */ ++ nreachable = 1; /* one context in the list */ + goto out; + } + +-- +2.25.4 + diff --git a/SPECS/libselinux.spec b/SPECS/libselinux.spec index 83af24c..804b5bb 100644 --- a/SPECS/libselinux.spec +++ b/SPECS/libselinux.spec @@ -6,7 +6,7 @@ %endif %define libsepolver 2.9-1 -%define libselinuxrelease 3 +%define libselinuxrelease 4 Summary: SELinux library and simple utilities Name: libselinux @@ -27,6 +27,7 @@ Patch0005: 0005-libselinux-add-missing-av_permission-values.patch Patch0006: 0006-libselinux-Use-Python-distutils-to-install-SELinux-p.patch Patch0007: 0007-libselinux-Do-not-use-SWIG_CFLAGS-when-Python-bindin.patch Patch0008: 0008-Fix-mcstrans-secolor-examples.patch +Patch0009: 0009-libselinux-Eliminate-use-of-security_compute_user.patch BuildRequires: gcc %if 0%{?with_ruby} @@ -274,6 +275,9 @@ rm -f %{buildroot}%{_mandir}/man8/togglesebool* %endif %changelog +* Thu Sep 24 2020 Vit Mojzis - 2.9-4 +- Eliminate use of security_compute_user() (#1879368) + * Fri Nov 08 2019 Vit Mojzis - 2.9-3 - Fix mcstrans secolor examples in secolor.conf man page (#1770270)