Ë
     OÝj6'  ã                   óT  — d Z ddlZddlZddlZddlmZmZmZmZm	Z	 g d¢Z
g d¢Z G d„ dej                  «      Z G d„ d	e«      Z G d
„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Zedk(  r ej.                  «        yy)z¢Gegenproben am iso_exec-Kaefig (Landlock+seccomp+rlimits), ohne systemd-Bus.
Startet NUR python3 / /bin/true im Kaefig, nie codex. Belegt M1/M2/M3(wrapper)/N1-N4.é    N)Ú
CAGE_PROBEÚPYTHONÚlandlock_abiÚrun_in_cageÚ	run_probe)ú/home/aria/.envz$/home/aria/.claude/.credentials.jsonz/home/aria/.codex/auth.json)z/home/aria/.sshz/home/aria/.claudez/home/aria/.config/ghc                   ó   — e Zd Zd„ Zd„ Zd„ Zy)ÚCageBasec                 ó´   — t        «       }|dk  r| j                  d|› d�«       t        j                  «       | _        | j                  j
                  | _        y )Né   zLandlock ABI z. < 4 auf diesem Host (Kaefig nicht einsetzbar))r   ÚskipTestÚtempfileÚTemporaryDirectoryÚ_tmpÚnameÚscratch)ÚselfÚabis     ú=/home/aria/aria-v3-dev/python/tests/test_isolation_wrapper.pyÚsetUpzCageBase.setUp   sE   € Ü‹nˆØ�Š7Ø�M‰M˜M¨#¨Ð.\Ð]Ô^Ü×/Ñ/Ó1ˆŒ	Ø—y‘y—~‘~ˆ�ó    c                 ó8   — | j                   j                  «        y )N)r   Úcleanup©r   s    r   ÚtearDownzCageBase.tearDown   s   € Ø�	‰	×ÑÕr   c                 óÖ   — t        | j                  |g|¢­i |¤Ž}| j                  |j                  d|› d|› d|j                  › d|j                  j                  d¬«      d d › �«       y )Nr   ú z: rc=z err=Úreplace©ÚerrorséÈ   )r   r   ÚassertEqualÚ
returncodeÚstderrÚdecode)r   ÚcheckÚargsÚkwÚrs        r   ÚassertProbezCageBase.assertProbe   sm   € Ü�d—l‘l EÐ7¨DÒ7°BÑ7ˆØ×Ñ˜Ÿ™ q¨U¨G°1°T°F¸%ÀÇÁ¸~ÈUÐST×S[ÑS[×SbÑSbÐjsÐSbÓStÐuyÐvyÐSzÐR{Ð*|Õ}r   N)Ú__name__Ú
__module__Ú__qualname__r   r   r*   © r   r   r
   r
      s   „ ò&òó~r   r
   c                   ó*   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚProdIsolationc                 óÌ   — t         D ]O  }t        j                  j                  |«      sŒ#| j	                  |¬«      5  | j                  d|«       d d d «       ŒQ y # 1 sw Y   Œ\xY w)N©Úpzread-denied)ÚPROD_SECRETSÚosÚpathÚexistsÚsubTestr*   ©r   r3   s     r   Ú"test_prod_secret_files_read_deniedz0ProdIsolation.test_prod_secret_files_read_denied"   sY   € Üò 	7ˆAÜ�w‰w�~‰~˜aÕ Ø—\‘\ A�\Ó&ñ 7Ø×$Ñ$ ]°AÔ6÷7ð 7ñ	7÷7ð 7úó   ¼AÁA#	c                 óÌ   — t         D ]O  }t        j                  j                  |«      sŒ#| j	                  |¬«      5  | j                  d|«       d d d «       ŒQ y # 1 sw Y   Œ\xY w)Nr2   zlist-denied)ÚPROD_SECRET_DIRSr5   r6   Úisdirr8   r*   r9   s     r   Ú!test_prod_secret_dirs_list_deniedz/ProdIsolation.test_prod_secret_dirs_list_denied(   sY   € Ü!ò 	7ˆAÜ�w‰w�}‰}˜QÕØ—\‘\ A�\Ó&ñ 7Ø×$Ñ$ ]°AÔ6÷7ð 7ñ	7÷7ð 7úr;   c                 ó(   — | j                  dd«       y )Núwrite-deniedr   ©r*   r   s    r   Útest_write_outside_rw_deniedz*ProdIsolation.test_write_outside_rw_denied.   s   € Ø×Ñ˜Ð):Õ;r   c                 óx   — | j                  dt        j                  j                  | j                  d«      «       y )Núwrite-okzok.txt)r*   r5   r6   Újoinr   r   s    r   Útest_write_in_rw_okz!ProdIsolation.test_write_in_rw_ok1   s%   € Ø×Ñ˜¤R§W¡W§\¡\°$·,±,ÀÓ%IÕJr   c                 óº  — dt        j                  d«      j                  «       z   }t         j                  j	                  d«      }|t         j                  d<   	 | j                  d«       |€!t         j                  j                  dd «       y |t         j                  d<   y # |€!t         j                  j                  dd «       w |t         j                  d<   w xY w)Nztest-é   ÚTELEGRAM_BOT_TOKENz	env-clean)r5   ÚurandomÚhexÚenvironÚgetr*   Úpop)r   ÚtokenÚsaveds      r   Útest_env_allowlist_no_leakz(ProdIsolation.test_env_allowlist_no_leak4   s¤   € Øœ"Ÿ*™* Q›-×+Ñ+Ó-Ñ-ˆÜ—
‘
—‘Ð3Ó4ˆØ+0Œ�
‰
Ð'Ñ(ð	9Ø×Ñ˜[Ô)àˆ}Ü—
‘
—‘Ð3°TÕ:à38”—
‘
Ð/Ò0øð ˆ}Ü—
‘
—‘Ð3°TÕ:à38”—
‘
Ð/Ò0ús   ÁB" Â"8CN)r+   r,   r-   r:   r?   rC   rG   rR   r.   r   r   r0   r0   !   s   „ ò7ò7ò<òKó
9r   r0   c                   óH   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zy)ÚSeccompRulesc                 ó&   — | j                  d«       y )Nzmemfd-deniedrB   r   s    r   Útest_memfd_create_deniedz%SeccompRules.test_memfd_create_deniedB   s   € Ø×Ñ˜Õ(r   c                 ó&   — | j                  d«       y )Nzexecveat-empty-deniedrB   r   s    r   Útest_execveat_empty_path_deniedz,SeccompRules.test_execveat_empty_path_deniedE   s   € Ø×ÑÐ0Õ1r   c                 ó&   — | j                  d«       y )Nzunshare-deniedrB   r   s    r   Útest_unshare_deniedz SeccompRules.test_unshare_deniedH   ó   € Ø×ÑÐ)Õ*r   c                 ó&   — | j                  d«       y )Nzkeyctl-deniedrB   r   s    r   Útest_keyctl_deniedzSeccompRules.test_keyctl_deniedK   ó   € Ø×Ñ˜Õ)r   c                 ó&   — | j                  d«       y )Nziouring-deniedrB   r   s    r   Útest_io_uring_deniedz!SeccompRules.test_io_uring_deniedN   r[   r   c                 ó&   — | j                  d«       y )Nzptrace-deniedrB   r   s    r   Útest_ptrace_deniedzSeccompRules.test_ptrace_deniedQ   r^   r   c                 ó(   — | j                  dd«       y )Nzkill-deniedÚ1rB   r   s    r   Útest_kill_foreign_pid_deniedz)SeccompRules.test_kill_foreign_pid_deniedT   s   € Ø×Ñ˜¨Õ,r   c                 ó(   — | j                  dd«       y )Nzaf-unix-deniedú/run/user/1001/busrB   r   s    r   Útest_af_unix_connect_deniedz(SeccompRules.test_af_unix_connect_deniedW   s   € Ø×ÑÐ)Ð+?Õ@r   c                 ó(   — | j                  dd«       y )Nzsendto-unix-deniedrg   rB   r   s    r   Útest_sendto_foreign_unix_deniedz,SeccompRules.test_sendto_foreign_unix_deniedZ   s   € Ø×ÑÐ-Ð/CÕDr   c                 ó&   — | j                  d«       y )Nzsocketpair-afunix-okrB   r   s    r   Ú%test_socketpair_af_unix_still_allowedz2SeccompRules.test_socketpair_af_unix_still_allowed]   s   € Ø×ÑÐ/Õ0r   N)r+   r,   r-   rV   rX   rZ   r]   r`   rb   re   rh   rj   rl   r.   r   r   rT   rT   A   s6   „ ò)ò2ò+ò*ò+ò*ò-òAòEó1r   rT   c                   óF   ‡ — e Zd ZdZˆ fd„Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
ˆ xZS )	ÚSeccompForeignProcessz©Review #8b/#8c: kein Zugriff auf FREMDE Prozesse (gleiche UID) ueber F_SETOWN/SIGIO,
    prlimit64 oder process_madvise. Wegwerf-Sleeper ausserhalb des Kaefigs als Ziel.c                 óØ   •— t         ‰| �  «        dd l}|j                  ddg«      | _        | j                  | j                  «       t        | j                  j                  «      | _	        y )Nr   z/usr/bin/sleepÚ60)
Úsuperr   Ú
subprocessÚPopenÚsleeperÚ
addCleanupÚ_kill_sleeperÚstrÚpidÚfpid)r   rr   Ú	__class__s     €r   r   zSeccompForeignProcess.setUpe   sO   ø€ Ü‰‰ŒÛØ!×'Ñ'Ð)9¸4Ð(@ÓAˆŒØ�‰˜×*Ñ*Ô+Ü˜Ÿ™×(Ñ(Ó)ˆ�	r   c                 ó�   — 	 | j                   j                  «        | j                   j                  d¬«       y # t        $ r Y y w xY w)Né   )Útimeout)rt   Ú	terminateÚwaitÚ	Exceptionr   s    r   rv   z#SeccompForeignProcess._kill_sleeperl   s>   € ð	Ø�L‰L×"Ñ"Ô$Ø�L‰L×Ñ aÐÕ(øÜò 	Ùð	ús   ‚69 ¹	AÁAc                 ó<   — | j                  d| j                  «       y )Nzfcntl-setown-denied©r*   ry   r   s    r   Ú test_fcntl_setown_foreign_deniedz6SeccompForeignProcess.test_fcntl_setown_foreign_denieds   s   € Ø×ÑÐ.°·	±	Õ:r   c                 ó(   — | j                  dd«       y )Nzfcntl-setsig-deniedÚ10rB   r   s    r   Útest_fcntl_setsig_deniedz.SeccompForeignProcess.test_fcntl_setsig_deniedv   s   € Ø×ÑÐ.°Õ5r   c                 ó<   — | j                  d| j                  «       y )Nzprlimit-foreign-deniedr‚   r   s    r   Útest_prlimit_foreign_deniedz1SeccompForeignProcess.test_prlimit_foreign_deniedy   ó   € Ø×ÑÐ1°4·9±9Õ=r   c                 ó&   — | j                  d«       y )Nzprlimit-self-okrB   r   s    r   Útest_prlimit_self_still_allowedz5SeccompForeignProcess.test_prlimit_self_still_allowed|   s   € Ø×ÑÐ*Õ+r   c                 ó<   — | j                  d| j                  «       y )Nzprocess-madvise-deniedr‚   r   s    r   Útest_process_madvise_deniedz1SeccompForeignProcess.test_process_madvise_denied   r‰   r   )r+   r,   r-   Ú__doc__r   rv   rƒ   r†   rˆ   r‹   r�   Ú__classcell__)rz   s   @r   rn   rn   a   s,   ø„ ñXô*òò;ò6ò>ò,ö>r   rn   c                   ó*   — e Zd Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚWrapperLimitsc                 óF   — | j                  ddt        d«      dddœ¬«       y )NÚrlimitÚASi    é   )r”   ÚNOFILE©Úrlimits)r*   rw   r   s    r   Útest_rlimit_as_set_in_wrapperz+WrapperLimits.test_rlimit_as_set_in_wrapper„   s*   € Ø×Ñ˜ 4¬Ð->Ó)?Ø(9ÀTÑ!Jð 	õ 	Lr   c                 ó4   — | j                  ddddddœ¬«       y )Nr“   ÚCPUÚ123é{   r•   )r›   r–   r—   rB   r   s    r   Útest_rlimit_cpu_set_in_wrapperz,WrapperLimits.test_rlimit_cpu_set_in_wrapperˆ   s   € Ø×Ñ˜ 5¨%ÀÐPTÑ9UÐÕVr   c                 ó2   — | j                  dddddi¬«       y )Nr“   r–   Ú777i	  r—   rB   r   s    r   Útest_rlimit_nofile_setz$WrapperLimits.test_rlimit_nofile_set‹   s   € Ø×Ñ˜ 8¨U¸XÀs¸OÐÕLr   c                 ó&   — | j                  d«       y )Nz	umask-077rB   r   s    r   Útest_umask_077zWrapperLimits.test_umask_077Ž   s   € Ø×Ñ˜Õ%r   c                 ó<   — | j                  d| j                  «       y )NÚcwd)r*   r   r   s    r   Útest_cwd_setzWrapperLimits.test_cwd_set‘   s   € Ø×Ñ˜ §¡Õ-r   N)r+   r,   r-   r™   rž   r¡   r£   r¦   r.   r   r   r‘   r‘   ƒ   s   „ òLòWòMò&ó.r   r‘   c                   ó   — e Zd Zd„ Zy)Ú
FdHandlingc           
      ó¾  — t        j                  dt         j                  «      }	 d| j                  dgdt        g| j                  gddiddid	œ}t        |t        d
t        dt        |«      g|f¬«      }| j                  |j                  d|j                  j                  d¬«      d d «       t        j                  |«       y # t        j                  |«       w xY w)Nz/etc/hostnamer   ú/usrú/etc/ld.so.cacheÚPATHú/usr/bin:/binr–   r•   ©Úmin_abir¥   ÚrxÚfile_roÚrwÚenvr˜   ú-Iz	fd-closed)Úpass_fdsr   r   r   r!   )r5   ÚopenÚO_RDONLYr   r   r   r   rw   r"   r#   r$   r%   Úclose)r   ÚfdÚcfgr)   s       r   Ú(test_inherited_fd_closed_before_restrictz3FdHandling.test_inherited_fd_closed_before_restrict–   s¶   € Ü�W‰W�_¤b§k¡kÓ2ˆð		à T§\¡\¸&¸Ø.´
Ð;ÀDÇLÁLÀ>Ø Ð0¸hÈÐ=MñˆCô
 ˜C¤&¨$´
¸KÌÈRËÐ!QÐ]_Ð\aÔbˆAØ×Ñ˜QŸ\™\¨1¨a¯h©h¯o©oÀY¨oÓ.OÐPTÐQTÐ.UÔVä�H‰H�R�LøŒB�H‰H�R�Lús   ¦B	C ÃCN)r+   r,   r-   r»   r.   r   r   r¨   r¨   •   s   „ ór   r¨   c                   ó$   — e Zd Zd„ Zd„ Zd„ Zd„ Zy)Ú
FailClosedc                 óÐ   — d| j                   | j                   gddiddidœ}t        |dg«      }| j                  |j                  d«       | j	                  d	|j
                  «       y )
Néc   r¬   r­   r–   é@   )r¯   r¥   r²   r³   r˜   ú/usr/bin/trueéF   s   ABI)r   r   r"   r#   ÚassertInr$   ©r   rº   r)   s      r   Ú test_abi_requirement_fail_closedz+FailClosed.test_abi_requirement_fail_closed¥   s^   € Ø T§\¡\¸$¿,¹,¸Ø˜Ð/¸XÀr¸NñLˆä˜˜oÐ.Ó/ˆØ×Ñ˜Ÿ™ rÔ*Ø�‰�f˜aŸh™hÕ'r   c                 ó  — t         j                  j                  | j                  d«      }t	        |d«      5 }|j                  d«       d d d «       t         j                  j                  | j                  d«      }t        j                  ||«       d| j                  dgd|g| j                  gdd	id
didœ}t        |dg«      }| j                  |j                  d«       | j                  d|j                  «       y # 1 sw Y   ŒµxY w)Nzreal.txtÚwÚxzlink.txtr   rª   r«   r¬   r­   r–   rÀ   r®   rÁ   rÂ   s   Symlink)r5   r6   rF   r   r¶   ÚwriteÚsymlinkr   r"   r#   rÃ   r$   )r   ÚtargetÚfhÚlinkrº   r)   s         r   Ú!test_symlink_config_path_rejectedz,FailClosed.test_symlink_config_path_rejected¬   sÖ   € Ü—‘—‘˜dŸl™l¨JÓ7ˆÜ�&˜#Óð 	 "Ø�H‰H�SŒM÷	ä�w‰w�|‰|˜DŸL™L¨*Ó5ˆÜ
�
‰
�6˜4Ô Ø D§L¡L¸¸Ø-¨tÐ4¸T¿\¹\¸NØ˜Ð/¸XÀr¸NñLˆô ˜˜oÐ.Ó/ˆØ×Ñ˜Ÿ™ rÔ*Ø�‰�j !§(¡(Õ+÷	ð 	ús   ·C=Ã=Dc                 óœ   — d| j                   dg| j                   gddiddidœ}t        |dg«      }| j                  |j                  d	«       y )
Nr   z/nonexistent/progr¬   r­   r–   rÀ   )r¯   r¥   Úfile_xr²   r³   r˜   rÁ   rÂ   )r   r   r"   r#   rÄ   s      r   Ú$test_missing_config_path_fail_closedz/FailClosed.test_missing_config_path_fail_closed¹   sU   € Ø D§L¡LÐ=PÐ<QØ—l‘l�^¨V°_Ð,EÐS[Ð]_ÐR`ñbˆä˜˜oÐ.Ó/ˆØ×Ñ˜Ÿ™ rÕ*r   c                 ó0   — | j                  dt        «       y )Nzexec-denied)r*   r   r   s    r   Ú"test_execute_nonallowlisted_deniedz-FailClosed.test_execute_nonallowlisted_denied¿   s   € à×Ñ˜¬
Õ3r   N)r+   r,   r-   rÅ   rÎ   rÑ   rÓ   r.   r   r   r½   r½   ¤   s   „ ò(ò,ò+ó4r   r½   c                   ó   — e Zd Zd„ Zd„ Zd„ Zy)ÚAuthReadonlyc           	      óÄ  — t         j                  j                  | j                  d«      }t         j                  j                  | j                  d«      }t        j                  |«       t        j                  |«       t         j                  j                  |d«      }t        |d«      5 }|j                  d«       d d d «       t        j                  ||rdnd«       t         j                  j                  |d«      }t        j                  ||«       |r|gng }dt        g|rg n|gz   }d	| j                  d
g||| j                  |gddiddidœ}	|	|fS # 1 sw Y   ŒšxY w)NÚauthdirz
codex-homez	auth.jsonrÇ   z{"token":"x"}i€  é   r«   r   rª   r¬   r­   r–   r•   )r¯   r¥   r°   r±   Úfile_rwr²   r³   r˜   )
r5   r6   rF   r   Úmkdirr¶   rÉ   ÚchmodrÊ   r   )
r   Úwritabler×   Ú
codex_homeÚauthrÌ   rÍ   rÙ   r±   rº   s
             r   Ú_stagezAuthReadonly._stageÅ   s  € Ü—'‘'—,‘,˜tŸ|™|¨YÓ7ˆÜ—W‘W—\‘\ $§,¡,°Ó=ˆ
Ü
�‰�ÔÜ
�‰�ÔÜ�w‰w�|‰|˜G [Ó1ˆÜ�$˜‹_ð 	& Ø�H‰H�_Ô%÷	&ä
�‰�¡‘u¨eÔ4Ü�w‰w�|‰|˜J¨Ó4ˆÜ
�
‰
�4˜ÔÙ$�4‘&¨"ˆØ%¤zÐ2¹H±bÈ4È&ÑQˆà §¡°f°XØ¨7Ø—<‘< Ð,Ø˜OÐ,¸(ÀDÐ9Iñ	
ˆð �DˆyÐ÷	&ð 	&ús   Â+EÅEc                 óz  — | j                  d¬«      \  }}t        |t        dt        d|g«      }| j	                  |j
                  d|j                  j                  d¬«      d d «       t        |t        dt        d	|g«      }| j	                  |j
                  d|j                  j                  d¬«      d d «       y )
NF©rÜ   r´   zread-okr   r   r   r!   rA   ©rß   r   r   r   r"   r#   r$   r%   )r   rº   rÍ   ÚroÚwrs        r   Ú#test_auth_copy_read_only_by_defaultz0AuthReadonly.test_auth_copy_read_only_by_defaultÚ   s¢   € Ø—K‘K¨�KÓ/‰	ˆˆTÜ˜œv t¬Z¸ÀDÐIÓJˆØ×Ñ˜Ÿ™¨¨2¯9©9×+;Ñ+;À9Ð+;Ó+MÈdÈsÐ+SÔTÜ˜œv t¬Z¸ÈÐNÓOˆØ×Ñ˜Ÿ™¨¨2¯9©9×+;Ñ+;À9Ð+;Ó+MÈdÈsÐ+SÕTr   c                 óÔ   — | j                  d¬«      \  }}t        |t        dt        d|g«      }| j	                  |j
                  d|j                  j                  d¬«      d d «       y )	NTrá   r´   rE   r   r   r   r!   râ   )r   rº   rÍ   rä   s       r   Ú$test_auth_copy_writable_when_enabledz1AuthReadonly.test_auth_copy_writable_when_enabledá   s\   € Ø—K‘K¨�KÓ.‰	ˆˆTÜ˜œv t¬Z¸ÀTÐJÓKˆØ×Ñ˜Ÿ™¨¨2¯9©9×+;Ñ+;À9Ð+;Ó+MÈdÈsÐ+SÕTr   N)r+   r,   r-   rß   rå   rç   r.   r   r   rÕ   rÕ   Ä   s   „ òò*UóUr   rÕ   c                   ó   — e Zd ZdZd„ Zy)ÚReadOnlyContentImmutablezåRe-Review 2: eine file_ro-Datei ist INHALTLICH unveraenderbar (Kernschutz gegen Nutzlast),
    auch wenn utimensat (touch) von Landlock nicht mediiert wird. Synthetische ro-Datei (kein echtes
    Home), deshalb nebenwirkungsfrei.c                 óJ  — dd l }dd l}|j                  «       }| j                  |j                  |d«       t
        j                  j                  |d«      }t        |dd¬«      5 }|j                  d«       d d d «       t        | j                  d||g|gd	œ¬
«      }| j                  |j                  d|j                  j                  d¬«      d d «       t        |d¬«      5 }| j                  |j!                  «       d«       d d d «       y # 1 sw Y   Œ˜xY w# 1 sw Y   y xY w)Nr   Tz
startup.rcrÇ   zutf-8)Úencodingz	ORIGINAL
zro-content-immutable)r±   rã   )Úextrar   r   r!   )Úshutilr   Úmkdtempru   Úrmtreer5   r6   rF   r¶   rÉ   r   r   r"   r#   r$   r%   Úread)r   Ú_shÚ_tfÚdrã   rÌ   r)   s          r   Ú5test_ro_file_content_immutable_touch_may_change_mtimezNReadOnlyContentImmutable.test_ro_file_content_immutable_touch_may_change_mtimeì   sö   € ÛÛØ�K‰K‹MˆØ�‰˜Ÿ
™
 A tÔ,Ü�W‰W�\‰\˜!˜\Ó*ˆÜ�"�c GÔ,ð 	#°Ø�H‰H�\Ô"÷	#ô �d—l‘lÐ$:¸BÐSUÐRVÐ_`Ð^aÑFbÔcˆØ×Ñ˜Ÿ™ q¨!¯(©(¯/©/À¨/Ó*KÈDÈSÐ*QÔRÜ�"˜wÔ'ð 	6¨2Ø×Ñ˜RŸW™W›Y¨Ô5÷	6ð 	6÷	#ð 	#ú÷
	6ð 	6ús   Á$DÃ#!DÄDÄD"N)r+   r,   r-   rŽ   rô   r.   r   r   ré   ré   ç   s   „ ñ)ó6r   ré   Ú__main__)rŽ   r5   r   ÚunittestÚtests.iso_helpersr   r   r   r   r   r4   r=   ÚTestCaser
   r0   rT   rn   r‘   r¨   r½   rÕ   ré   r+   Úmainr.   r   r   ú<module>rú      s¿   ðñYã 	Û Û ç VÕ Vò€ò
 VÐ ô~ˆx× Ñ ô ~ô 9�Hô 9ô@1�8ô 1ô@>˜Hô >ôD.�Hô .ô$�ô ô4�ô 4ô@ U�8ô  UôF6˜xô 6ð( ˆzÒØ€H‡M�M…Oð r   