selinux/secilc/docs/cil_container_statements.md
James Carter 4878981229 libsepol/secilc/docs: Update the CIL documentation
Update the CIL documentation for the in-statement processing and
duplicate macro and block declarations with block inheritance.

Duplicate macro and block declarations are allowed if they occur as
the result of block inheritance. Document the fact that inherited
macros are overridden by any macros already declared in a
namespace and that declaring a block in a namespace that will
inherit a block with the same name can be used to allow in-statements
to be used on the block.

The new in-statement syntax still supports the old syntax but adds
the ability to specify whether the in-statement should be resolved
before or after block inheritance is resolved.

Signed-off-by: James Carter <jwcart2@gmail.com>
2021-09-07 10:28:46 -04:00

11 KiB

Container Statements

block

Start a new namespace.

Not allowed in macro and optional blocks.

sensitivity and category statements are not allowed in block blocks.

Duplicate declarations of a block in the same namespace will normally cause an error, but inheriting a block into a namespace (with blockinherit) that already has a block with the same name will only result in a warning message and not cause an error. The policy from both blocks will end up in the binary policy. This behavior was used in the past to allow a block to be declared so that an in-statement could be used on it, but now an in-statement can be specified to occur after inheritance, so this behavior is not necessary (but is still allowed).

Statement definition:

    (block block_id
        cil_statement
        ...
    )

Where:

block

The block keyword.

block_id

The namespace identifier.

cil_statement

Zero or more valid CIL statements.

Example:

See the blockinherit statement for an example.

blockabstract

Declares the namespace as a 'template' and does not generate code until instantiated by another namespace that has a blockinherit statement.

Not allowed in macro and optional blocks.

Statement definition:

    (block block_id
        (blockabstract template_id)
        cil_statement
        ...
    )

Where:

block

The block keyword.

block_id

The namespace identifier.

blockabstract

The blockabstract keyword.

template_id

The abstract namespace identifier. This must match the block_id entry.

cil_statement

Zero or more valid CIL statements forming the abstract block.

Example:

See the blockinherit statement for an example.

blockinherit

Used to add common policy rules to the current namespace via a template that has been defined with the blockabstract statement. All blockinherit statements are resolved first and then the contents of the block are copied. This is so that inherited blocks will not be inherited. For a concrete example, please see the examples section.

Inherited rules are resolved by searching namespaces in the following order:

  • The parent namespaces (if any) where the blockinherit rule is located with the exception of the global namespace.

  • The parent namespaces of the block being inherited (but not that block's namespace) with the exception of the global namespace.

  • The global namespace.

Not allowed in macro blocks.

Statement definition:

    (block block_id
        (blockinherit template_id)
        cil_statement
        ...
    )

Where:

block

The block keyword.

block_id

The namespace identifier.

blockinherit

The blockinherit keyword.

template_id

The inherited namespace identifier.

cil_statement

Zero or more valid CIL statements.

Example:

This example contains a template client_server that is instantiated in two blocks (netserver_app and netclient_app):

    ; This is the template block:
    (block client_server
        (blockabstract client_server)

        ; Log file labeling
        (type log_file)
        (typeattributeset file_type (log_file))
        (typeattributeset data_file_type (log_file))
        (allow process log_file (dir (write search create setattr add_name)))
        (allow process log_file (file (create open append getattr setattr)))
        (roletype object_r log_file)
        (context log_file_context (u object_r log_file low_low))

        ; Process labeling
        (type process)
        (typeattributeset domain (process))
        (call app_domain (process))
        (call net_domain (process))
    )

    ; This is a policy block that will inherit the abstract block above:
    (block netclient_app
        ; Add common policy rules to namespace:
        (blockinherit client_server)
        ; Label the log files
        (filecon "/data/data/com.se4android.netclient/.*" file log_file_context)
    )

    ; This is another policy block that will inherit the abstract block above:
    (block netserver_app
       ; Add common policy rules to namespace:
        (blockinherit client_server)

        ; Label the log files
        (filecon "/data/data/com.se4android.netserver/.*" file log_file_context)
    )

    ; This is an example of how blockinherits resolve inherits before copying
    (block a
        (type one))

    (block b
        ; Notice that block a is declared here as well
        (block a
            (type two)))

    ; This will first copy the contents of block b, which results in type b.a.two being copied.
    ; Next, the contents of block a will be copied which will result in type a.one.
    (block ab
        (blockinherit b)
        (blockinherit a))

optional

Declare an optional namespace. All CIL statements in the optional block must be satisfied before instantiation in the binary policy.

Not allowed in booleanif blocks.

tunable, in, block, blockabstract, and macro statements are not allowed in optional blocks.

Statement definition:

    (optional optional_id
        cil_statement
        ...
    )

Where:

optional

The optional keyword.

optional_id

The optional namespace identifier.

cil_statement

Zero or more valid CIL statements.

Example:

This example will instantiate the optional block ext_gateway.move_file into policy providing all optional CIL statements can be resolved:

    (block ext_gateway
        ......
        (optional move_file
            (typetransition process msg_filter.move_file.in_queue file msg_filter.move_file.in_file)
            (allow process msg_filter.move_file.in_queue (dir (read getattr write search add_name)))
            (allow process msg_filter.move_file.in_file (file (write create getattr)))
            (allow msg_filter.move_file.in_file unconfined.object (filesystem (associate)))
            (typetransition msg_filter.int_gateway.process msg_filter.move_file.out_queue file
                msg_filter.move_file.out_file)
            (allow msg_filter.int_gateway.process msg_filter.move_file.out_queue (dir (read write search)))
            (allow msg_filter.int_gateway.process msg_filter.move_file.out_file (file (read getattr unlink)))
        ) ; End optional block

        .....
    ) ; End block

in

Allows the insertion of CIL statements into a named container (block, optional or macro). This insertion can be specified to occur either before or after block inheritance has been resolved.

Not allowed in macro, booleanif, and other in blocks.

tunable and in statements are not allowed in in blocks.

Statement definition:

    (in [before|after] container_id
        cil_statement
        ...
    )

Where:

in

The in keyword.

before|after

An optional value that specifies whether to process the [`in`](cil_container_statements.md#in) before or after block inheritance. If no value is specified, then the [`in`](cil_container_statements.md#in) will be processed before block inheritance.

container_id

A valid block, optional or macro namespace identifier.

cil_statement

Zero or more valid CIL statements.

Example:

This will add rules to the container named system_server:

    (in system_server
        (dontaudit process secmark_demo.dns_packet (packet (send recv)))
        (allow process secmark_demo.dns_packet (packet (send recv)))
    )