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
This commit is contained in:
Ellen Arteca 2024-04-22 18:30:45 +00:00
parent 81bf7bd5a7
commit 7cf8c71868

View file

@ -382,21 +382,25 @@ static int check_neverallows(policydb_t *policydb, char *text, char *end)
char *p, *start; char *p, *start;
int result; 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; p = text;
bool in_comment = false;
while (p < end) { while (p < end) {
while (p < end && isspace(*p)) if (*p == '#') in_comment = true;
p++; if (!in_comment || *p == '\n') *cur_non_comment_text++ = *p;
if (*p == '\n') in_comment = false;
if (*p == '#') { ++p;
while (p < end && *p != '\n') }
p++; p = non_comment_text;
continue; end = cur_non_comment_text;
} while (p < end) {
while (p < end && isspace(*p)) p++;
start = p; start = p;
while (p < end && !isspace(*p)) while (p < end && !isspace(*p)) p++;
p++;
len = p - start; len = p - start;
if (len != keyword_size || strncmp(start, keyword, keyword_size)) if (len != keyword_size || strncmp(start, keyword, keyword_size))
continue; continue;
@ -437,8 +441,10 @@ static int check_neverallows(policydb_t *policydb, char *text, char *end)
result = check_assertions(NULL, policydb, neverallows); result = check_assertions(NULL, policydb, neverallows);
avrule_list_destroy(neverallows); avrule_list_destroy(neverallows);
free(non_comment_text);
return result; return result;
err: err:
free(non_comment_text);
if (errno == ENOMEM) { if (errno == ENOMEM) {
fprintf(stderr, "Out of memory while parsing neverallow rules\n"); fprintf(stderr, "Out of memory while parsing neverallow rules\n");
} else } else