libselinux, sefcontext_compile: handle NULL pcre study data

pcre_study() can return a NULL result if no additional information
could be determined for the pattern.  Thus, sefcontext_compile
needs to correctly handle the case where the study data is NULL
when generating file_contexts.bin, and libselinux needs to correctly
handle it when loading file_contexts.bin.  Fix them both.

This change enables:
semanage fcontext -a -t httpd_exec_t "(/.*)?"
to succeed, since the regex itself is valid but there is no
additional information produced by pcre_study().

Reported-by: Vit Mojzis <vmojzis@redhat.com>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
This commit is contained in:
Stephen Smalley 2016-08-17 14:52:00 -04:00
parent dbc6d6d596
commit 6e2bdb770f
3 changed files with 33 additions and 22 deletions

View File

@ -388,18 +388,21 @@ static int load_mmap(struct selabel_handle *rec, const char *path,
rc = -1;
goto err;
}
spec->lsd.study_data = (void *)mmap_area->next_addr;
spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA;
rc = next_entry(NULL, mmap_area, entry_len);
if (rc < 0)
goto err;
/* Check that study data lengths match. */
rc = pcre_fullinfo(spec->regex, &spec->lsd,
PCRE_INFO_STUDYSIZE, &len);
if (rc < 0 || len != entry_len) {
rc = -1;
goto err;
if (entry_len) {
spec->lsd.study_data = (void *)mmap_area->next_addr;
spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA;
rc = next_entry(NULL, mmap_area, entry_len);
if (rc < 0)
goto err;
/* Check that study data lengths match. */
rc = pcre_fullinfo(spec->regex, &spec->lsd,
PCRE_INFO_STUDYSIZE, &len);
if (rc < 0 || len != entry_len) {
rc = -1;
goto err;
}
}
data->nspec++;

View File

@ -80,9 +80,12 @@ struct saved_data {
static inline pcre_extra *get_pcre_extra(struct spec *spec)
{
if (spec->from_mmap)
return &spec->lsd;
else
if (spec->from_mmap) {
if (spec->lsd.study_data)
return &spec->lsd;
else
return NULL;
} else
return spec->sd;
}

View File

@ -228,10 +228,13 @@ static int write_binary_file(struct saved_data *data, int fd)
if (len != to_write)
goto err;
/* determine the size of the pcre study info */
rc = pcre_fullinfo(re, sd, PCRE_INFO_STUDYSIZE, &size);
if (rc < 0)
goto err;
if (sd) {
/* determine the size of the pcre study info */
rc = pcre_fullinfo(re, sd, PCRE_INFO_STUDYSIZE, &size);
if (rc < 0)
goto err;
} else
size = 0;
/* write the number of bytes in the pcre study data */
to_write = size;
@ -239,10 +242,12 @@ static int write_binary_file(struct saved_data *data, int fd)
if (len != 1)
goto err;
/* write the actual pcre study data as a char array */
len = fwrite(sd->study_data, 1, to_write, bin_file);
if (len != to_write)
goto err;
if (sd) {
/* write the actual pcre study data as a char array */
len = fwrite(sd->study_data, 1, to_write, bin_file);
if (len != to_write)
goto err;
}
}
rc = 0;