From 7cf8c718682222bf9fa78ef7ec3aadd14a01e8e8 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Mon, 22 Apr 2024 18:30:45 +0000 Subject: [PATCH] Fix the neverallow parser so it can parse comments The neverallow parser has a bug where it cannot parse multiline neverallow rules that have inline comments. For example (taken from the bug description): ``` neverallow appdomain system_server:udp_socket {accept append bind create ioctl listen lock name_bind relabelfrom relabelto setattr shutdown }; ``` Initially, the plan to fix this was to use the existing `avrule_read` function the libsepol parser, however this function expects a compiled `policy` file that represents the policies to be read in, while the neverallow parser reads from a `.te` file or a string. This CL implements a fix to this parsing issue by pre-parsing the string (either read in from a file or passed in as a string directly) and removing the comments, before proceeding with the parsing as before. Bug: 334697757 Test: atest android.security.cts.SELinuxNeverallowRulesTest Change-Id: Ica67dedc23ca9c8b5ba8566198b6bfa785780921 --- tools/sepolicy-analyze/neverallow.c | 30 +++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tools/sepolicy-analyze/neverallow.c b/tools/sepolicy-analyze/neverallow.c index a55a92171..745ab1333 100644 --- a/tools/sepolicy-analyze/neverallow.c +++ b/tools/sepolicy-analyze/neverallow.c @@ -382,21 +382,25 @@ static int check_neverallows(policydb_t *policydb, char *text, char *end) char *p, *start; int result; + int non_comment_len = 0, cur_non_comment_len = 0; + char *cur_non_comment_text = calloc(1, (end - text) + 1); + char *non_comment_text = cur_non_comment_text; + if (!cur_non_comment_text) + goto err; p = text; + bool in_comment = false; while (p < end) { - while (p < end && isspace(*p)) - p++; - - if (*p == '#') { - while (p < end && *p != '\n') - p++; - continue; - } - + if (*p == '#') in_comment = true; + if (!in_comment || *p == '\n') *cur_non_comment_text++ = *p; + if (*p == '\n') in_comment = false; + ++p; + } + p = non_comment_text; + end = cur_non_comment_text; + while (p < end) { + while (p < end && isspace(*p)) p++; start = p; - while (p < end && !isspace(*p)) - p++; - + while (p < end && !isspace(*p)) p++; len = p - start; if (len != keyword_size || strncmp(start, keyword, keyword_size)) continue; @@ -437,8 +441,10 @@ static int check_neverallows(policydb_t *policydb, char *text, char *end) result = check_assertions(NULL, policydb, neverallows); avrule_list_destroy(neverallows); + free(non_comment_text); return result; err: + free(non_comment_text); if (errno == ENOMEM) { fprintf(stderr, "Out of memory while parsing neverallow rules\n"); } else