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