0451adebdf
Nicolas Iooss reports: I am continuing to investigate OSS-Fuzz crashes and the following one is quite complex. Here is a CIL policy which triggers a heap-use-after-free error in the CIL compiler: (class CLASS (PERM2)) (classorder (CLASS)) (classpermission CLSPRM) (optional o (mlsvalidatetrans x (domby l1 h1)) (common CLSCOMMON (PERM1)) (classcommon CLASS CLSCOMMON) ) (classpermissionset CLSPRM (CLASS (PERM1))) The issue is that the mlsvalidatetrans fails to resolve in pass CIL_PASS_MISC3, which comes after the resolution of classcommon (in pass CIL_PASS_MISC2). So: * In pass CIL_PASS_MISC2, the optional block still exists, the classcommon is resolved and class CLASS is linked with common CLSCOMMON. * In pass CIL_PASS_MISC3, the optional block is destroyed, including the common CLSCOMMON. * When classpermissionset is resolved, function cil_resolve_classperms uses "common_symtab = &class->common->perms;", which has been freed. The use-after-free issue occurs in __cil_resolve_perms (in libsepol/cil/src/cil_resolve_ast.c): // common_symtab was freed rc = cil_symtab_get_datum(common_symtab, curr->data, &perm_datum); The fundamental problem here is that when the optional block is disabled it is immediately destroyed in the middle of the pass, so the class has not been reset and still refers to the now destroyed common when the classpermissionset is resolved later in the same pass. Added a list, disabled_optionals, to struct cil_args_resolve which is passed when resolving the tree. When optionals are disabled, they are now added to this list and then are destroyed after the tree has been reset between passes. Reported-by: Nicolas Iooss <nicolas.iooss@m4x.org> Signed-off-by: James Carter <jwcart2@gmail.com> Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org> |
||
---|---|---|
.. | ||
cil | ||
include | ||
man | ||
src | ||
tests | ||
utils | ||
.gitignore | ||
COPYING | ||
Makefile | ||
VERSION |