<!-- Common Interface Language (CIL) Reference Guide -->
<!-- class_and_permission_statements.xml -->
<sect1>
<title>Class and Permission Statements</title>
<sect2 id="common">
<title>common</title>
<para>Declares a common identifier in the current namespace with a set of common permissions that can be used by one or more <literal><link linkend="class">class</link></literal> identifiers. The <literal><link linkend="classcommon">classcommon</link></literal> statement is used to associate a <literal><link linkend="common">common</link></literal> identifier to a specific <literal><link linkend="class">class</link></literal> identifier.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(common common_id (permission_id ...))]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal><link linkend="common">common</link></literal></para>
</entry>
<entry>
<para>The <literal><link linkend="common">common</link></literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>common_id</literal></para>
</entry>
<entry>
<para>The <literal><link linkend="common">common</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>permission_id</literal></para>
</entry>
<entry>
<para>One or more permissions.</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Example:</emphasis></para>
<para>This common statement will associate the <literal><link linkend="common">common</link></literal> identifier '<literal>file</literal>' with the list of permissions:</para>
<programlisting><![CDATA[
(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))]]>
</programlisting>
</sect2>
<sect2 id="classcommon">
<title>classcommon</title>
<para>Associate a <literal><link linkend="class">class</link></literal> identifier to a one or more permissions declared by a <literal><link linkend="common">common</link></literal> identifier.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(classcommon class_id common_id)]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal><link linkend="classcommon">classcommon</link></literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classcommon">classcommon</link></literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>class_id</literal></para>
</entry>
<entry>
<para>A single previously declared <literal><link linkend="class">class</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>common_id</literal></para>
</entry>
<entry>
<para>A single previously declared <literal><link linkend="common">common</link></literal> identifier that defines the common permissions for that class.</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Example:</emphasis></para>
<para>This associates the <literal>dir</literal> class with the list of permissions declared by the <literal>file common</literal> identifier:</para>
<programlisting><![CDATA[
(common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
(classcommon dir file)]]>
</programlisting>
</sect2>
<sect2 id="class">
<title>class</title>
<para>Declares a class and zero or more permissions in the current namespace.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(class class_id (permission_id ...))]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal><link linkend="class">class</link></literal></para>
</entry>
<entry>
<para>The <literal><link linkend="class">class</link></literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>class_id</literal></para>
</entry>
<entry>
<para>The <literal><link linkend="class">class</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>permission_id</literal></para>
</entry>
<entry>
<para>Zero or more permissions declared for the class. Note that if zero permissions, an empty list is required as shown in the example.</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Examples:</emphasis></para>
<para>This example defines a set of permissions for the <literal>binder</literal> class indentifier:</para>
<programlisting><![CDATA[(class binder (impersonate call set_context_mgr transfer receive))]]>
</programlisting>
<para>This example defines a common set of permissions to be used by the <literal>sem</literal> class, the <literal>(class sem ())</literal> does not define any other permissions (i.e. an empty list):</para>
<programlisting><![CDATA[
(common ipc (create destroy getattr setattr read write associate unix_read unix_write))
(classcommon sem ipc)
(class sem ())]]>
</programlisting>
<simpara>and will produce the following set of permissions for the <literal>sem</literal> class identifier of:</simpara>
<programlisting><![CDATA[(class sem (create destroy getattr setattr read write associate unix_read unix_write))]]>
</programlisting>
<para>This example, with the following combination of the <literal><link linkend="common">common</link></literal>, <literal><link linkend="classcommon">classcommon</link></literal> and <literal><link linkend="class">class</link></literal> statements:</para>
<programlisting><![CDATA[
(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))]]>
</programlisting>
<simpara>will produce a set of permissions for the <literal>dir</literal> class identifier of:</simpara>
<programlisting><![CDATA[(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))]]>
</programlisting>
</sect2>
<sect2 id="classorder">
<title>classorder</title>
<para>Defines the order of <link linkend="class">class</link>'s. This is a mandatory statement. Multiple <literal>classorder</literal> statements declared in the policy will form an ordered list.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(classorder (class_id ...))]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal>classorder</literal></para>
</entry>
<entry>
<para>The <literal>classorder</literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>class_id</literal></para>
</entry>
<entry>
<para>One or more <literal><link linkend="class">class</link></literal> identifiers.</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Example:</emphasis></para>
<para>This will produce an ordered list of "<literal>file dir process</literal>"</para>
<programlisting><![CDATA[
(class process)
(class file)
(class dir)
(classorder (file dir))
(classorder (dir process))]]>
</programlisting>
</sect2>
<sect2 id="classpermission">
<title>classpermission</title>
<para>Declares a class permission set identifier in the current namespace that can be used by one or more <literal><link linkend="classpermissionset">classpermissionset</link></literal>s to associate one or more classes and permissions to form a named set.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(classpermission classpermissionset_id)]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal><link linkend="classpermission">classpermission</link></literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classpermission">classpermission</link></literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>classpermissionset_id</literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classpermissionset">classpermissionset</link></literal> identifier.</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Example:</emphasis></para>
<para>See the <literal><link linkend="classpermissionset">classpermissionset</link></literal> statement for examples.</para>
</sect2>
<sect2 id="classpermissionset">
<title>classpermissionset</title>
<para>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 <literal>classpermissionset</literal>s may be used in av rules and constraints.</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(classpermissionset classpermissionset_id (class_id (permission_id | expr ...)))]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2.25 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal><link linkend="classpermissionset">classpermissionset</link></literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classpermissionset">classpermissionset</link></literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>classpermissionset_id</literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classpermissionset">classpermissionset</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>class_id</literal></para>
</entry>
<entry>
<para>A single previously declared <literal><link linkend="class">class</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>permission_id</literal></para>
</entry>
<entry>
<para>Zero or more permissions required by the class.</para>
<para>Note that there must be at least one <literal>permission</literal> identifier or <literal>expr</literal> declared).</para>
</entry>
</row>
<row>
<entry>
<para><literal>expr</literal></para>
</entry>
<entry>
<para>Zero or more <literal>expr</literal>'s, the valid operators and syntax are:</para>
<simpara><literal> (and (permission_id ...) (permission_id ...))</literal></simpara>
<simpara><literal> (or (permission_id ...) (permission_id ...))</literal></simpara>
<simpara><literal> (xor (permission_id ...) (permission_id ...))</literal></simpara>
<simpara><literal> (not (permission_id ...))</literal></simpara>
<simpara><literal> (all)</literal></simpara>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Examples:</emphasis></para>
<para>These class permission set statements will resolve to the permission sets shown in the kernel policy language <literal><link linkend="allow">allow</link></literal> rules:</para>
<programlisting><![CDATA[
(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 } ;]]>
</programlisting>
</sect2>
<sect2 id="classmap">
<title>classmap</title>
<para>Declares a class map identifier in the current namespace and one or more class mapping identifiers. This will allow:</para>
<orderedlist>
<listitem><para>Multiple <literal><link linkend="classpermissionset">classpermissionset</link></literal>s to be linked to a pair of <literal><link linkend="classmap">classmap</link></literal> / <literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para></listitem>
<listitem><para>Multiple <literal><link linkend="class">class</link></literal>s to be associated to statements and rules that support a list of classes:</para>
<simplelist type="inline">
<member><literal><link linkend="typetransition">typetransition</link></literal></member>
<member><literal><link linkend="typechange">typechange</link></literal></member>
<member><literal><link linkend="typemember">typemember</link></literal></member>
<member><literal><link linkend="rangetransition">rangetransition</link></literal></member>
<member><literal><link linkend="roletransition">roletransition</link></literal></member>
<member><literal><link linkend="defaultuser">defaultuser</link></literal></member>
<member><literal><link linkend="defaultrole">defaultrole</link></literal></member>
<member><literal><link linkend="defaulttype">defaulttype</link></literal></member>
<member><literal><link linkend="defaultrange">defaultrange</link></literal></member>
<member><literal><link linkend="validatetrans">validatetrans</link></literal></member>
<member><literal><link linkend="mlsvalidatetrans">mlsvalidatetrans</link></literal></member>
</simplelist></listitem>
</orderedlist>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(classmap classmap_id (classmapping_id ...))]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal><link linkend="classmap">classmap</link></literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classmap">classmap</link></literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>classmap_id</literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>classmapping_id</literal></para>
</entry>
<entry>
<para>One or more <literal><link linkend="classmapping">classmapping</link></literal> identifiers.</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Example:</emphasis></para>
<para>See the <literal><link linkend="classmapping">classmapping</link></literal> statement for examples.</para>
</sect2>
<sect2 id="classmapping">
<title>classmapping</title>
<para>Define sets of <literal><link linkend="classpermissionset">classpermissionset</link></literal>s (named or anonymous) to form a consolidated <literal><link linkend="classmapping">classmapping</link></literal> set. Generally there are multiple <literal><link linkend="classmapping">classmapping</link></literal> statements with the same <literal><link linkend="classmap">classmap</link></literal> and <literal><link linkend="classmapping">classmapping</link></literal> identifiers that form a set of different <literal><link linkend="classpermissionset">classpermissionset</link></literal>'s. This is useful when multiple class / permissions are required in rules such as the <literal><link linkend="allow">allow</link></literal> rules (as shown in the examples).</para>
<para><emphasis role="bold">Statement definition:</emphasis></para>
<programlisting><![CDATA[(classmapping classmap_id classmapping_id classpermissionset_id)]]></programlisting>
<para><emphasis role="bold">Where:</emphasis></para>
<informaltable frame="all">
<tgroup cols="2">
<colspec colwidth="2.25 *"/>
<colspec colwidth="6 *"/>
<tbody>
<row>
<entry>
<para><literal><link linkend="classmapping">classmapping</link></literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classmapping">classmapping</link></literal> keyword.</para>
</entry>
</row>
<row>
<entry>
<para><literal>classmap_id</literal></para>
</entry>
<entry>
<para>A single previously declared <literal><link linkend="classmap">classmap</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>classmapping_id</literal></para>
</entry>
<entry>
<para>The <literal><link linkend="classmapping">classmapping</link></literal> identifier.</para>
</entry>
</row>
<row>
<entry>
<para><literal>classpermissionset_id</literal></para>
</entry>
<entry>
<para>A single named <literal><link linkend="classpermissionset">classpermissionset</link></literal> identifier or a single anonymous <literal><link linkend="classpermissionset">classpermissionset</link></literal> using <literal>expr</literal>'s as required (see the <literal><link linkend="classpermissionset">classpermissionset</link></literal> statement).</para>
</entry>
</row>
</tbody></tgroup>
</informaltable>
<para><emphasis role="bold">Examples:</emphasis></para>
<para>These class mapping statements will resolve to the permission sets shown in the kernel policy language <literal><link linkend="allow">allow</link></literal> rules:</para>
<programlisting><![CDATA[
(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 } ;]]>
</programlisting>
</sect2>
</sect1>