The commit d155b410d4 (libsepol/cil:
Check for duplicate blocks, optionals, and macros) fixed a bug
that allowed duplicate blocks, optionals, and macros with the same
name in the same namespace. For blocks and macros, a duplicate
is always a problem, but optional block names are only used for
in-statement resolution. If no in-statement refers to an optional
block, then it does not matter if more than one with same name
exists.
One easy way to generate multiple optional blocks with the same
name declaration is to call a macro with an optional block multiple
times in the same namespace.
As an example, here is a portion of CIL policy
(macro m1 ((type t))
(optional op1
(allow t self (CLASS (PERM)))
)
)
(type t1)
(call m1 (t1))
(type t2)
(call m1 (t2))
This will result in two optional blocks with the name op1.
There are three parts to allowing multiple optional blocks with
the same name declaration.
1) Track an optional block's enabled status in a different way.
One hinderance to allowing multiple optional blocks with the same
name declaration is that they cannot share the same datum. This is
because the datum is used to get the struct cil_optional which has
the enabled field and each block's enabled status is independent of
the others.
Remove the enabled field from struct cil_optional, so it only contains
the datum. Use a stack to track which optional blocks are being
disabled, so they can be deleted in the right order.
2) Allow multiple declarations of optional blocks.
Update cil_allow_multiple_decls() so that a flavor of CIL_OPTIONAL
will return CIL_TRUE. Also remove the check in cil_copy_optional().
3) Check if an in-statement refers to an optional with multiple
declarations and exit with an error if it does.
Signed-off-by: James Carter <jwcart2@gmail.com>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>