<!-- 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>