Re: [PATCH] mcstrans: escape config text spliced into build_regexps() patterns

James Carter <[email protected]>
Newsgroups org.kernel.vger.selinux
Message-ID <CAP+JOzQnq8khhFY43BSytNv-Z8JSimhAYrCzz6xQqBpVyGXG2A@mail.gmail.com>
On Thu, Aug 13, 2026 at 2:41 PM Stephen Smalley
<[email protected]> wrote:
>
> build_regexps() interpolates the base-classification, prefix/suffix
> affix, word and Whitespace strings from the setrans configuration
> directly into PCRE alternation patterns. A label containing a PCRE
> metacharacter such as "." or "(" therefore either fails to compile,
> matches unintended input, or produces a pathological regex that a
> client can drive via TRANS_TO_RAW_CONTEXT. The Whitespace value goes
> into a character class, where an unescaped "-" between two characters
> is treated as a range and "]" ends the class early.
>
> Backslash-escape the fixed PCRE metacharacter set when appending
> config-supplied text; the same escaping is safe both inside and
> outside a character class. None of the shipped example configurations
> carry metacharacters in these fields, so behaviour is unchanged for
> them. The configuration is root-owned, so this is hardening rather
> than a boundary crossing.
>
> Signed-off-by: Stephen Smalley <[email protected]>

Acked-by: James Carter <[email protected]>

> ---
>  mcstrans/src/mcstrans.c | 42 ++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 37 insertions(+), 5 deletions(-)
>
> diff --git a/mcstrans/src/mcstrans.c b/mcstrans/src/mcstrans.c
> index 89235269..9704f5dc 100644
> --- a/mcstrans/src/mcstrans.c
> +++ b/mcstrans/src/mcstrans.c
> @@ -1074,6 +1074,32 @@ static int buf_append(char **buf, size_t *cap, size_t *len, const char *s)
>         return 0;
>  }
>
> +/*
> + * Append s with PCRE metacharacters backslash-escaped so it matches
> + * literally.  Used for config-supplied label/word/affix/whitespace
> + * text spliced into the alternation patterns in build_regexps().
> + * Works both inside and outside a character class.
> + */
> +static int buf_append_literal(char **buf, size_t *cap, size_t *len,
> +                             const char *s)
> +{
> +       char esc[3] = { '\\', 0, 0 };
> +       char lit[2] = { 0, 0 };
> +
> +       for (; *s; s++) {
> +               if (strchr("\\^$.|?*+()[]{}-", *s)) {
> +                       esc[1] = *s;
> +                       if (buf_append(buf, cap, len, esc))
> +                               return -1;
> +               } else {
> +                       lit[0] = *s;
> +                       if (buf_append(buf, cap, len, lit))
> +                               return -1;
> +               }
> +       }
> +       return 0;
> +}
> +
>  static void build_regexp(pcre2_code **r, char *buffer)
>  {
>         int error;
> @@ -1106,6 +1132,11 @@ static int build_regexps(domain_t *domain)
>                 if (buf_append(&buffer, &cap, &len, (s))) \
>                         goto err;                         \
>         } while (0)
> +#define APPEND_LIT(s)                                             \
> +       do {                                                      \
> +               if (buf_append_literal(&buffer, &cap, &len, (s))) \
> +                       goto err;                                 \
> +       } while (0)
>  #define RESET()                           \
>         do {                              \
>                 len = 0;                  \
> @@ -1133,7 +1164,7 @@ static int build_regexps(domain_t *domain)
>         qsort(sortable, n_el, sizeof(char *), string_size);
>
>         for (i = 0; i < n_el; i++) {
> -               APPEND(sortable[i]);
> +               APPEND_LIT(sortable[i]);
>                 if (i != (n_el - 1))
>                         APPEND("|");
>         }
> @@ -1149,7 +1180,7 @@ static int build_regexps(domain_t *domain)
>                 if (g->prefixes) {
>                         APPEND("(?:");
>                         for (a = g->prefixes; a; a = a->next) {
> -                               APPEND(a->text);
> +                               APPEND_LIT(a->text);
>                                 if (a->next)
>                                         APPEND("|");
>                         }
> @@ -1185,13 +1216,13 @@ static int build_regexps(domain_t *domain)
>                         if (i)
>                                 APPEND("|");
>                         APPEND("\\b");
> -                       APPEND(g->sword[i]->text);
> +                       APPEND_LIT(g->sword[i]->text);
>                         APPEND("\\b");
>                 }
>
>                 if (g->whitespace) {
>                         APPEND("|[");
> -                       APPEND(g->whitespace);
> +                       APPEND_LIT(g->whitespace);
>                         APPEND("]+");
>                 }
>
> @@ -1208,7 +1239,7 @@ static int build_regexps(domain_t *domain)
>                         APPEND("[       ]+");
>                         APPEND("(?:");
>                         for (a = g->suffixes; a; a = a->next) {
> -                               APPEND(a->text);
> +                               APPEND_LIT(a->text);
>                                 if (a->next)
>                                         APPEND("|");
>                         }
> @@ -1227,6 +1258,7 @@ err:
>         free(buffer);
>         return -1;
>  #undef APPEND
> +#undef APPEND_LIT
>  #undef RESET
>  }
>
> --
> 2.55.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.