# Class and Permission Statements

## common

Declares a common identifier in the current namespace with a set of common permissions that can be used by one or more `class` identifiers. The `classcommon` statement is used to associate a `common` identifier to a specific `class` identifier.

Statement definition:

    (common common_id (permission_id ...))

Where:

`common` | The `common` keyword.
`common_id` | The `common` identifier.
`permission_id` | One or more permissions.

Example:

This common statement will associate the `common` identifier '`file`' with the list of permissions:

    (common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))

## classcommon

Associate a `class` identifier to a one or more permissions declared by a `common` identifier.

Statement definition:

    (classcommon class_id common_id)

Where:

`classcommon` | The `classcommon` keyword.
`class_id` | A single previously declared `class` identifier.
`common_id` | A single previously declared `common` identifier that defines the common permissions for that class.

Example:

This associates the `dir` class with the list of permissions declared by the `file common` identifier:

    (common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))

    (classcommon dir file)

## class

Declares a class and zero or more permissions in the current namespace.

Statement definition:

    (class class_id (permission_id ...))

Where:

`class` | The `class` keyword.
`class_id` | The `class` identifier.
`permission_id` | Zero or more permissions declared for the class. Note that if zero permissions, an empty list is required as shown in the example.

Examples:

This example defines a set of permissions for the `binder` class indentifier:

    (class binder (impersonate call set_context_mgr transfer receive))

This example defines a common set of permissions to be used by the `sem` class, the `(class sem ())` does not define any other permissions (i.e. an empty list):

    (common ipc (create destroy getattr setattr read write associate unix_read unix_write))

    (classcommon sem ipc)
    (class sem ())

and will produce the following set of permissions for the `sem` class identifier of:

    (class sem (create destroy getattr setattr read write associate unix_read unix_write))

This example, with the following combination of the `common`, `classcommon` and `class` statements:

    (common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))

    (classcommon dir file)
    (class dir (add_name remove_name reparent search rmdir open audit_access execmod))

will produce a set of permissions for the `dir` class identifier of:

    (class dir (add_name remove_name reparent search rmdir open audit_access execmod ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))

## classorder

Defines the order of class's. This is a mandatory statement. Multiple `classorder` statements declared in the policy will form an ordered list.

Statement definition:

    (classorder (class_id ...))

Where:

`classorder` | The `classorder` keyword.
`class_id` | One or more `class` identifiers.

Example:

This will produce an ordered list of "`file dir process`"

    (class process)
    (class file)
    (class dir)
    (classorder (file dir))
    (classorder (dir process))

## classpermission

Declares a class permission set identifier in the current namespace that can be used by one or more `classpermissionset`s to associate one or more classes and permissions to form a named set.

Statement definition:

    (classpermission classpermissionset_id)

Where:

`classpermission` | The `classpermission` keyword.
`classpermissionset_id` | The `classpermissionset` identifier.

Example:

See the `classpermissionset` statement for examples.

## classpermissionset

Defines a class permission set identifier in the current namespace that associates a class and one or more permissions to form a named set. Nested expressions may be used to determine the required permissions as shown in the examples. Anonymous `classpermissionset`s may be used in av rules and constraints.

Statement definition:

    (classpermissionset classpermissionset_id (class_id (permission_id | expr ...)))

Where:

`classpermissionset` | The `classpermissionset` keyword.
`classpermissionset_id` | The `classpermissionset` identifier.
`class_id` | A single previously declared `class` identifier.
`permission_id` | Zero or more permissions required by the class. Note that there must be at least one `permission` identifier or `expr` declared).
`expr` | Zero or more `expr`'s, the valid operators and syntax are: `(and (permission_id ...) (permission_id ...))` `(or (permission_id ...) (permission_id ...))` `(xor (permission_id ...) (permission_id ...))` `(not (permission_id ...))` `(all)`

Examples:

These class permission set statements will resolve to the permission sets shown in the kernel policy language `allow` rules:

    (class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))

    (type test_1)
    (type test_2)
    (type test_3)
    (type test_4)
    (type test_5)

    ; NOT
    (classpermission zygote_1)
    (classpermissionset zygote_1 (zygote
        (not
            (specifyinvokewith specifyseinfo)
        )
    ))
    (allow unconfined.process test_1 zygote_1)
    ;; allow unconfined.process test_1 : zygote { specifyids specifyrlimits specifycapabilities } ;

    ; AND - ALL - NOT - Equiv to test_1
    (classpermission zygote_2)
    (classpermissionset zygote_2 (zygote
        (and
            (all)
            (not (specifyinvokewith specifyseinfo))
        )
    ))
    (allow unconfined.process test_2 zygote_2)
    ;; allow unconfined.process test_2 : zygote { specifyids specifyrlimits specifycapabilities  } ;

    ; OR
    (classpermission zygote_3)
    (classpermissionset zygote_3 (zygote ((or (specifyinvokewith) (specifyseinfo)))))
    (allow unconfined.process test_3 zygote_3)
    ;; allow unconfined.process test_3 : zygote { specifyinvokewith specifyseinfo } ;

    ; XOR - This will not produce an allow rule as the XOR will remove all the permissions:
    (classpermission zygote_4)
    (classpermissionset zygote_4 (zygote (xor (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo) (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))))

    ; ALL
    (classpermission zygote_all_perms)
    (classpermissionset zygote_all_perms (zygote (all)))
    (allow unconfined.process test_5 zygote_all_perms)
    ;; allow unconfined.process test_5 : zygote { specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo } ;

## classmap

Declares a class map identifier in the current namespace and one or more class mapping identifiers. This will allow:

1. Multiple `classpermissionset`s to be linked to a pair of `classmap` / `classmapping` identifiers.

2. Multiple `class`s to be associated to statements and rules that support a list of classes:

   - `typetransition`
   - `typechange`
   - `typemember`
   - `rangetransition`
   - `roletransition`
   - `defaultuser`
   - `defaultrole`
   - `defaulttype`
   - `defaultrange`
   - `validatetrans`
   - `mlsvalidatetrans`

Statement definition:

    (classmap classmap_id (classmapping_id ...))

Where:

`classmap` | The `classmap` keyword.
`classmap_id` | The `classmap` identifier.
`classmapping_id` | One or more `classmapping` identifiers.

Example:

See the `classmapping` statement for examples.

## classmapping

Define sets of `classpermissionset`s (named or anonymous) to form a consolidated `classmapping` set. Generally there are multiple `classmapping` statements with the same `classmap` and `classmapping` identifiers that form a set of different `classpermissionset`'s. This is useful when multiple class / permissions are required in rules such as the `allow` rules (as shown in the examples).

Statement definition:

    (classmapping classmap_id classmapping_id classpermissionset_id)

Where:

`classmapping` | The `classmapping` keyword.
`classmap_id` | A single previously declared `classmap` identifier.
`classmapping_id` | The `classmapping` identifier.
`classpermissionset_id` | A single named `classpermissionset` identifier or a single anonymous `classpermissionset` using `expr`'s as required (see the `classpermissionset` statement).

Examples:

These class mapping statements will resolve to the permission sets shown in the kernel policy language `allow` rules:

    (class binder (impersonate call set_context_mgr transfer receive))
    (class property_service (set))
    (class zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith specifyseinfo))

    (classpermission cps_zygote)
    (classpermissionset cps_zygote (zygote (not (specifyids))))

    (classmap android_classes (set_1 set_2 set_3))

    (classmapping android_classes set_1 (binder (all)))
    (classmapping android_classes set_1 (property_service (set)))
    (classmapping android_classes set_1 (zygote (not (specifycapabilities))))

    (classmapping android_classes set_2 (binder (impersonate call set_context_mgr transfer)))
    (classmapping android_classes set_2 (zygote (specifyids specifyrlimits specifycapabilities specifyinvokewith)))

    (classmapping android_classes set_3 cps_zygote)
    (classmapping android_classes set_3 (binder (impersonate call set_context_mgr)))

    (block map_example
        (type type_1)
        (type type_2)
        (type type_3)

        (allow type_1 self (android_classes (set_1)))
        (allow type_2 self (android_classes (set_2)))
        (allow type_3 self (android_classes (set_3)))
    )

    ; The above will resolve to the following AV rules:
    ;; allow map_example.type_1 map_example.type_1 : binder { impersonate call set_context_mgr transfer receive } ;
    ;; allow map_example.type_1 map_example.type_1 : property_service set ;
    ;; allow map_example.type_1 map_example.type_1 : zygote { specifyids specifyrlimits specifyinvokewith specifyseinfo } ;

    ;; allow map_example.type_2 map_example.type_2 : binder { impersonate call set_context_mgr transfer } ;
    ;; allow map_example.type_2 map_example.type_2 : zygote { specifyids specifyrlimits specifycapabilities specifyinvokewith } ;

    ;; allow map_example.type_3 map_example.type_3 : binder { impersonate call set_context_mgr } ;
    ;; allow map_example.type_3 map_example.type_3 : zygote { specifyrlimits specifycapabilities specifyinvokewith specifyseinfo } ;