+
    lHàjô?  ã                  óÄ  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
t
^ RIt^ RIHt ^ RIHt ^ RIHt ^ RIHt ^ RIHt ]P,                  ! ]4      t^
tRt. R.Ot. R/Ot/ tR	]R
&   R R ltR R lt R R lt!R R lt"R R lt#R R lt$R R lt%R R lt&R R lt'R R lt(R R  lt)R! R" lt*R# R$ lt+R%t,]-! 4       t.R&]R'&   R0R( R) llt/R* R+ lt0R, R- lt1R# )1a*  Hand root-written sandbox files back to the host user when a root Docker container is removed.

The Docker backend runs the image's default user (root) unless ``docker_run_as_host_user`` is set,
so everything the container writes into the Hermes-created bind mounts (``<sandbox>/home`` at
``/root``, ``<sandbox>/workspace`` at ``/workspace``) lands on the host owned by uid 0, and the user
cannot delete it. Until the container is removed, a root container with its volumes can ``chown``
those trees back; once it is gone only ``sudo`` can. The handback runs after it stopped, so files a
process writes on shutdown are included.

Persistent sandbox dirs outlive their container, and root refuses some host-owned files: git stops
at "dubious ownership", ssh at "Bad owner" on ``~/.ssh/config``. So the handback records the exact
paths it changes beside the dirs (on the host, outside every mount), and the next container that
mounts them gives exactly those paths back to root before its first command. Files the user added
on the host in between keep their owner. Every walk is ``find -P`` (no symlinks followed) and prunes
each mount Docker reports nested under the sandbox paths (read-only skills, credentials, caches,
``docker_volumes`` and ``docker_extra_args`` binds), so host data outside the sandbox dir is never touched.

After the handback, a root pass strips setuid/setgid bits (``chmod ug-s``) from the sandbox files
whatever their owner (a host-user-owned group-root setgid file runs with host egid 0). A container
that could write file capabilities (SETFCAP, ALL, privileged) instead gets every regular file
re-chowned to its own uid, which clears the bits and ``security.capability`` and changes no owner.
A persistent container is never removed, so it gets this strip when a session detaches from it,
before reattaching and before the stale-container sweep removes it. The strip reads the sandbox
binds from the container itself (a container shared across profiles has its creator's dirs) but
only keeps those under a sandbox root this host derives from its own Hermes root.
)ÚannotationsN)ÚPath)ÚOptional)Úget_default_hermes_root)Úget_sandbox_dir)Úrun_capturez.hermes-owner-handbackzdict[str, bool]Ú_remapping_cachec               ó    € V ^8„  d   QhRRRR/# )é   Ú
docker_exeÚstrÚreturnÚbool© )Úformats   "ÚH/home/ubuntu/.hermes/hermes-agent/tools/environments/docker_ownership.pyÚ__annotate__r   =   s   € ÷ (ñ ( Sð (¨Tñ (ó    c                óœ  € V \         9  dv    \        V RRR.^
R7      pVP                  ^ 8X  d   VP                  P	                  4       MRpVP                  4       '       * ;'       g    RV9   ;'       g    R	V9   \         V &   \         V ,          #   \
        P                  \        3 d#   p\        P                  RT4       Rp Rp?L{Rp?ii ; i)
a  True when container uid 0 is not host uid 0 (rootless Docker, userns-remap) or when that
cannot be told. Chowning to the host uid there maps to a subordinate id and makes the files
less reachable, so the handback is skipped. Cached per executable for the process.Úinfoz--formatz{{.SecurityOptions}}©ÚtimeoutÚ z-docker info for ownership handback failed: %sNÚrootlessÚuserns)r   r   Ú
returncodeÚstdoutÚlowerÚ
subprocessÚTimeoutExpiredÚOSErrorÚloggerÚdebugÚstrip)r   ÚresultÚoptionsÚes   &   r   Ú_daemon_remaps_usersr'   =   s¸   € ð Ô)Ô)ð	Ü  *¨f°jÐBXÐ!YÐceÔfˆFØ/5×/@Ñ/@ÀAÔ/E�f—m‘m×)Ñ)Ô+È2ˆGð ,3¯=©=«?Ô':×'jÐ'j¸jÈGÑ>S×'jÐ'jÐW_ÐcjÑWjÔ˜Ñ$Ü˜JÕ'Ð'øô	 ×)Ñ)¬7Ð3ô 	Ü�L‰LÐHÈ!ÔLØ�Gûð	ús   �>B ÂCÂ)CÃCc               ó    € V ^8„  d   QhRRRR/# )r
   r   r   r   zOptional[tuple[int, int]]r   )r   s   "r   r   r   L   s   € ÷ Vñ V˜cð VÐ&?ñ Vr   c                óÞ   € \         P                  R8w  g   \        P                  ! 4       ^ 8X  d   R# \	        V 4      '       d   R# \        P                  ! 4       \        P
                  ! 4       3# )zÞHost ``(uid, gid)`` to hand sandbox files to, or ``None`` when no handback applies: the
host is not Linux (Docker Desktop bind mounts are not root-owned on the host), Hermes itself
runs as root, or the daemon remaps users.ÚlinuxN)ÚsysÚplatformÚosÚgeteuidr'   Úgetegid)r   s   &r   Ú_handback_idsr0   L   sF   € ô ‡|�|�wÔ¤"§*¢*£,°!Ô"3ÙÜ'¨
×3Ò3ˆ4ÐU¼"¿*º*»,ÌÏ
Ê
ËÐ9UÐUr   c               ó    € V ^8„  d   QhRRRR/# )r
   Úmountsúlist[tuple[str, str]]r   zOptional[Path]r   )r   s   "r   r   r   U   s   € ÷ Kñ KÐ.ð K°>ñ Kr   c                ór   € V '       d/   \        V ^ ,          ^ ,          4      P                  \        ,          # R# )zUThe record lives in the per-task sandbox dir, the parent of every Hermes bind source.N)r   ÚparentÚHANDBACK_RECORD)r2   s   &r   Ú_record_pathr7   U   s'   € ç:@Œ4��q•	˜!•Ó×$Ñ$¤Õ6ÐJÀdÐJr   c               ó$   € V ^8„  d   QhRRRRRR/# )r
   r   r   Úcontainer_idr   úOptional[dict]r   )r   s   "r   r   r   Z   s!   € ÷ 
ñ 
˜ð 
¨Cð 
°Nñ 
r   c                óF  €  \        V RV.^
R7      pVP                  ^ 8X  d(   \        P                  ! VP                  4      ^ ,          #  R#   \
        P                  \        \        \        \        3 d*   p\        P                  RTR,          T4        Rp?R# Rp?ii ; i)a   The container's ``docker inspect`` record (its real user, image id and every mount,
``docker_extra_args`` binds and named volumes included), or ``None`` when Docker cannot say
(then nothing is walked: a same-filesystem bind is invisible to ``find -xdev``).Úinspectr   zdocker inspect of %s failed: %sºNé   NN)r   r   ÚjsonÚloadsr   r   r   r    Ú
ValueErrorÚ
IndexErrorÚKeyErrorr!   r"   )r   r9   r$   r&   s   &&  r   Ú_inspectrD   Z   sŒ   € ðNÜ˜j¨)°\ÐBÈBÔOˆØ×Ñ Ô!Ü—:’:˜fŸm™mÓ,¨QÕ/Ð/ð "ñ øô ×%Ñ%¤w´
¼JÌÐQô NÜ�‰Ð6¸ÀSÕ8IÈ1×MÐMÙûðNús   ‚AA Á*B Á7BÂB c               ó    € V ^8„  d   QhRRRR/# ©r
   r   Údictr   r   r   )r   s   "r   r   r   g   s   € ÷ ]ñ ]˜ð ] ñ ]r   c                óœ   € V P                  R4      ;'       g    / P                  R4      ;'       g    RP                  R4      ^ ,          R9   # )z]The container's effective user (``--user`` from any source, else the image ``USER``) is root.ÚConfigÚUserr   Ú:)r   ÚrootÚ0)ÚgetÚsplit)r   s   &r   Ú_runs_as_rootrP   g   sB   € à�X‰X�hÓ×%Ð% 2×*Ñ*¨6Ó2×8Ð8°b×?Ñ?ÀÓDÀQÕGÐK\Ñ\Ð\r   c               ó    € V ^8„  d   QhRRRR/# rF   r   )r   s   "r   r   r   l   s   € ÷ `ñ `˜Tð ` dñ `r   c                óH  € V P                  R4      ;'       g    / p\        VP                  R4      4      ;'       gg    \        ;QJ d5    R VP                  R4      ;'       g    .  4       F  '       g   K   R# 	  R# ! R VP                  R4      ;'       g    .  4       4      # )z«Only a container granted SETFCAP (or privileged) can write file capabilities; the base
args drop it. ``find`` cannot test xattrs, so then every regular file is re-chowned.Ú
HostConfigÚ
Privilegedc              3  ód   "  € T F&  qP                  4       P                  R 4      R9   x € K(  	  R# 5i)ÚCAP_N)ÚSETFCAPÚALL)ÚupperÚremoveprefix)Ú.0Úcs   & r   Ú	<genexpr>Ú%_may_set_file_caps.<locals>.<genexpr>p   s*   é € ð /`ÙF^À�‰‹	×Ñ˜vÓ&Ð*<Ö<ÓF^ùs   ‚.0ÚCapAddTF)rN   r   Úany)r   Úhosts   & r   Ú_may_set_file_capsrb   l   s£   € ð �8‰8�LÓ!×'Ð' R€DÜ�—‘˜Ó&Ó'÷ `ð `¯3«3ñ /`ØFJÇhÁhÈxÓFX×F^ÐF^Ð\^ÐF^ó/`¯3¬3ð `ª3ð `¨3ñ /`ØFJÇhÁhÈxÓFX×F^ÐF^Ð\^ÐF^ó/`ó ,`ð `r   c               ó    € V ^8„  d   QhRRRR/# )r
   r   rG   r   r3   r   )r   s   "r   r   r   t   s   € ÷ 
wñ 
w˜ð 
wÐ"7ñ 
wr   c           	     ó�  € \        4       pV.VP                  R4      O Uu0 uF0  p\        P                  P	                  VR,          R,          4      kK2  	  ppVP                  \        P                  P	                  \        4       R,          4      4       V P                  R4      ;'       g    .  Uu. uF|  pVP                  R4      R8X  g   K  VP                  R4      R
9   g   K3  \        P                  P	                  VP                  R4      ;'       g    R	4      VP                  R4      3NK~  	  ppV UUu. uFr  w  rg\        P                  P                  V4      '       g   K,  \        P                  P                  \        P                  P                  V4      4      V9   g   Ko  Wg3NKt  	  upp# u upi u upi u uppi )ax  The container's Hermes sandbox binds (``<root>/<task>/{home,workspace}`` at ``/root`` and
``/workspace``) as ``(realpath, destination)``. *root* is derived on this host only, never from
container metadata (labels and binds are settable via extra args or the image): this process's
``<sandbox>/docker`` or the default one of any profile of this Hermes root (shared containers).z
profiles/*Ú	sandboxesÚdockerÚMountsÚTypeÚbindÚDestinationÚSourcez/nonexistent)z/rootz
/workspace)
r   Úglobr-   ÚpathÚrealpathÚaddr   rN   ÚisdirÚdirname)r   Úhermes_rootÚdÚrootsÚmÚbindsÚsrcÚdsts   &       r   Ú_sandbox_bindsry   t   se  € ô
 *Ó+€KØDOÐCqÐR]×RbÑRbÐcoÓRpÑCqÓrÑCq¸aŒR�W‰W×Ñ˜a +�o°Õ8Ö9ÑCq€EÐrØ	‡I�IŒb�g‰g×ÑœÓ0°8Õ;Ó<Ô=Øbf×bjÑbjÐksÓbt×bzÐbzÐxzÐbzó ]ÑbzÐ]^Ø—‘�f“ Ñ'ô YØ,-¯E©E°-Ó,@ÐD[Ñ,[ô YŒb�g‰g×Ñ˜qŸu™u X›×@Ð@°.ÓAÀ1Ç5Á5ÈÓCWÓXÑbz€Eð ]á',Ôv¡u™8˜3´·±·±¸c×0BŒJÄrÇwÁwÇÁÔWY×W^ÑW^×WfÑWfÐgjÓWkÓGlÐpuÑGuŒJˆS‹J¡uÒvÐvùò	 sùò]ùãvs/   ¡6F8Â3F=ÃF=Ã(0F=ÄF=Ä<)GÅ*>GÆ-Gc               ó    € V ^8„  d   QhRRRR/# )r
   ÚownerÚintr   ú	list[str]r   )r   s   "r   r   r   �   s   € ÷ lñ l�#ð l˜)ñ lr   c                ó2   € R RRRRRRRRRR\        V 4      R.# )	Ú(ú-typeÚfú-ors   ÚlÚ)z-userz-print0)r   )r{   s   &r   Ú_ownedr…   �   s+   € à�˜#˜t W¨c°4¸À#ÀsÈGÔUXÐY^ÓU_ÐajÐkÐkr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   r2   r3   Úmount_pointsr}   Útailr   r   )r   s   "r   r   r   †   s0   € ÷ uñ uÐ+ð u¸9ð uÈIð uÐZcñ ur   c                óÐ  a€ V  UUu. uF  w  r4VNK	  	  ppp. p\        V Uu0 uF  qwP                  R4      kK  	  up4       Fu  o\        ;QJ d    V3R lV 4       F  '       g   K   RM	  RM! V3R lV 4       4      '       g   KE  T. V'       d   R.M. ORN\        P                  ! RRS4      N,          pKw  	  R	R
.VORNV'       d   R.VORNRNRNOVO# . OVO# u uppi u upi )z˜``find`` argv applying *tail* to every entry under the sandbox mounts. It never follows
symlinks (``-P``) and prunes each mount point nested below them.Ú/c              3  ór   <"  € T F,  pSP                  VP                  R 4      R ,           4      x € K.  	  R# 5i)rŠ   N)Ú
startswithÚrstrip)r[   ÚtÚpoints   & €r   r]   Úwalk_argv.<locals>.<genexpr>Œ   s,   øé € ÐF¹g¸ˆu×Ñ §¡¨£°Õ 3×4Ð4»gùs   ƒ47TFr‚   z-pathz
([][*?\\])z\\\1z/usr/bin/findz-Pz-xdevr   r„   z-prune)Úsortedr�   r`   ÚreÚsub)	r2   r‡   rˆ   Ú_Ú	containerÚtargetsÚpruneÚpr�   s	   &&&     @r   Ú	walk_argvr™   †   sè   ø€ ñ .4Ô4©V™\˜Q‹y©V€GÑ4Ø€EÜ±Ó=±¨1Ÿ™ #ž±Ñ=Ö>ˆß‹3ÔF¹gÓF�3�3Š3ÔF¹gÓF×FÔFØÐa§%˜™¨RÐa°'Ða¼2¿6º6À-ÐQXÐZ_Ó;`ÐaÕaŠEñ ?ð ˜TÐt GÐt¨WÐt×^c¸Ð8Z¸uÐ8ZÀcÐ8ZÈ8Ð8ZÐUYÐ8ZÐtÐosÐtÐtÐikÐtÐosÐtÐtùó 5ùâ=s
   ‡C¢C#c               ó4   € V ^8„  d   QhRRRRRRRRR	R
RRRR/# )r
   r   r   Útargetr}   r2   r3   r   rG   r{   r|   ÚdeadlineÚfloatr   zOptional[list[bytes]]r   )r   s   "r   r   r   ‘   sB   € ÷ 	8ñ 	8�cð 	8 9ð 	8Ð6Kð 	8ÐSWð 	8Ð`cð 	8Øð	8Ø3ñ	8r   c                óä  € VP                  R4      ;'       g    .  Uu. uF  qfR,          NK  	  pp\        W\        W'\        V4      4      V4      pVP                  ^ 8w  dS   \
        P                  RVP                  VP                  P                  RR4      P                  4       R,          4       R# VP                  P                  R4       U	u. uF  q™'       g   K  V	NK  	  up	# u upi u up	i )	zWEntries owned by *owner*, or ``None`` when the walk failed (its output may be partial).rg   rj   zownership walk exited %d: %súutf-8Úreplace:Niô  NNó    )rN   Ú_dockerr™   r…   r   r!   r"   ÚstderrÚdecoder#   r   rO   )
r   r›   r2   r   r{   rœ   ru   Úpointsr$   r˜   s
   &&&&&&    r   Ú_walkr¦   ‘   sÎ   € ð )-¯©°Ó(:×(@Ð(@¸bÐ(@ÓAÑ(@ 1�×ÐÑ(@€FÐAÜ�Z¬°6Ä6È%Ã=Ó)QÐS[Ó\€FØ×Ñ˜AÔÜ�‰Ð3°V×5FÑ5FØ—]‘]×)Ñ)¨'°9Ó=×CÑCÓEÀdÕKô	MáØ—}‘}×*Ñ*¨5Ô1Ó7Ñ1�!³Q�AˆAÑ1Ñ7Ð7ùò Bùò 8s   žC(Ã	C-ÃC-c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   r   r   r›   r}   Úargvrœ   r�   r   )r   s   "r   r   r   �   s(   € ÷ 
ñ 
˜ð 
 Yð 
°ið 
È5ñ 
r   c                ó‚  €  TP                  RRV9   d   RM\        P                  4      p\        P                  ! V .VOVO3RRRVR\	        RV\
        P                  ! 4       ,
          4      RR	/VB #   \        P                   d7    R
T9   d.   \        T RRYP                  R
4      ^,           ,          .^
R7       h i ; i)zŠRun *argv* in *target*. A timeout only kills the CLI, so a named throwaway is removed then
instead of running on with the sandbox volumes.ÚstdinÚinputNÚcapture_outputTr   g      ð?ÚcheckFú--nameÚrmz-fr   )
Úpopr   ÚDEVNULLÚrunÚmaxÚtimeÚ	monotonicr   r   Úindex)r   r›   r¨   rœ   Úkwargsrª   s   &&&&, r   r¢   r¢   �   sÍ   € ðØ—
‘
˜7¨G°vÔ,=¡DÄ:×CUÑCUÓVˆÜ�~Š~˜zÐ:¨FÐ:°TÐ:ñ dÈ4ð dÐW\ð dÜ&)¨#¨x¼$¿.º.Ó:JÕ/JÓ&KðdØSXðdØ\bñdð 	døä×$Ñ$ô Ø�vÔÜ˜ T¨4°¿¹ÀXÓ8NÐQRÕ8RÕ1SÐTÐ^`ÕaØðús   ‚A0A3 Á3AB>c               ó0   € V ^8„  d   QhRRRRRRRRRR	R
R/# )r
   r   r   r›   r}   Úpathszlist[bytes]r{   rœ   r�   r   r   r   )r   s   "r   r   r   ª   s8   € ÷ "ñ "�sð " Ið "°kð "È#ð "ÐY^ð "Ðcgñ "r   c                óÚ   € \        WR RRRRVR.VRP                  R V 4       4      R7      pVP                  ^ 8w  d!   \        P	                  R	W5P                  4       VP                  ^ 8H  # )
z/usr/bin/xargsz-0z-rz
/bin/chownz-hz--r   c              3  ó2   "  € T F  qR ,           x € K  	  R# 5i©r¡   Nr   )r[   r˜   s   & r   r]   Ú_chown.<locals>.<genexpr>¬   s   é € Ð#=±u°!¨§I¢I³uùs   ‚)r«   zownership chown to %s exited %d)r¢   Újoinr   r!   r"   )r   r›   r¹   r{   rœ   r$   s   &&&&& r   Ú_chownr¿   ª   sl   € Ü�ZÐ*:¸DÀ$ÈÐVZÐ\aÐcgÐ)hÐjrØŸ8™8Ñ#=±uÓ#=Ó=ô?€Fà×Ñ˜AÔÜ�‰Ð6¸×?PÑ?PÔQØ×Ñ Ñ!Ð!r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   r9   r   r   rG   Úvolumesr}   r   r   )r   s   "r   r   r   ²   s(   € ÷ 9ñ 9˜Sð 9¨ð 9°yð 9ÀYñ 9r   c                óŠ   € . RO\         O\        ORNRV R,           R\        P                  ! ^4       2NVORNRNVR,          N# )	r²   r®   zhermes-handback-r=   Ú-z--entrypointr   ÚImage)	r²   z--rmú-iz--pullÚneverz	--networkÚnonez--userú0:0)Ú_THROWAWAY_CONFINEMENTÚ	_SAFE_ENVÚsecretsÚ	token_hex)r9   r   rÁ   s   &&&r   Ú
_throwawayrÍ   ²   sp   € ò9Ô[qð 9Üð9Ø ð9Ø$4°\À#Õ5FÐ4GÀqÌ×IZÒIZÐ[\ÓI]ÐH^Ð"_ð9àð9à$ð9à&(ð9à*.¨w­-ð9ð 9r   z¥uids=$("$@" -type f -exec stat -c %u -- {} +) || exit; for u in $(printf "%s\n" "$uids" | sort -u); do "$@" -type f -user "$u" -exec chown -h "$u" {} + || exit; donezset[str]Ú_strip_warnedc               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   r   r   r9   r   r:   r   ÚNoner   )r   s   "r   r   r   À   s)   € ÷ !ñ !¨ð !¸Cð !À~ð !Ðaeñ !r   c                ó|  € Vf   \        V 4      '       d   \        W4      MRpV'       d   \        V4      '       d   \        V4      M. ;p'       g   R# \	        YV UUUu. uF  w  rERRV RV 23 F  pVNK  	  K  	  uppp4      pR.\        Y2P                  R4      ;'       g    .  Uu. uF  qˆR,          NK  	  up. 4      R,          Op	\        V4      '       d   R	R
\        R.V	OM. V	ORNRNRNRNRNRNRNRNRNp
 \        WV
\        P                  ! 4       \        ,           4      pVP                  ;'       d4    RVP                   RVP                  P                  RR4      R,           2pV'       d…   \(        P*                  P-                  V^ ,          ^ ,          4      pV\.        9   d   \0        P2                  M\0        P4                  ! RWìP7                  4       4       \.        P9                  V4       R# R# u upppi u upi   \         P"                  \$        3 d   p\'        T4      p Rp?LÅRp?ii ; i)a»  Strip setuid/setgid bits (and file caps, when the container could set them) from the root
container's existing sandbox binds in ONE throwaway that mounts only those dirs: owners stay,
so a running container's git/ssh checks keep passing, and a path swapped mid-walk can only
lead to sandbox files, never other host data. ``--mount`` refuses a missing source instead
of creating it root-owned. A pass that cannot run warns once per sandbox dir.Nz--mountztype=bind,src=z,dst=Úfindrg   rj   :é   NNz/bin/shz-cÚshr€   r�   z-permz/6000z-execÚchmodzug-sz{}Ú+zexit z: rŸ   r    :Ni,  Nz�Could not strip setuid/setgid bits and file capabilities from Docker sandbox %s (%s); files there may still run with elevated rights on the host)r0   rD   rP   ry   rÍ   r™   rN   rb   Ú_SAME_OWNER_CHOWNr¢   r´   rµ   Ú_CHOWN_TIMEOUT_Sr   r£   r¤   r   r   r    r   r-   rm   rq   rÎ   r!   r"   Úwarningr#   ro   )r   r9   r   r2   rw   rx   Úar›   ru   Úwalkr¨   r$   Úerrorr&   Úwheres   &&&            r   Ústrip_sandbox_privilegesrÞ   À   s'  € ð ‚|Ü5BÀ:×5NÒ5NŒx˜
Ô1ÐTXˆß.2´}ÀT×7JÒ7J”n TÔ*ÐPRÐRˆFÖRÙÜ˜¹võ -e¹v±8°3Ø7@ÀNÐSVÐRWÐW\Ð]`Ð\aÐBbÓ6c°ó ./Ù6cñ ./¹vó -eó f€Fð Ðe”Y˜vÇ(Á(È8ÓBT×BZÐBZÐXZÐBZÓ'[ÑBZ¸Q¨-×(8Ð(8ÑBZÑ'[Ð]_Ó`ÐacÕdÐe€DÜASÐTX×AYÒAYˆY˜Ô/°Ð=¸Ñ=Ø]�4Ð]˜Ð] #Ð] wÐ]°Ð]¸Ð]À'Ð]È6Ð]ÐSWÐ]ÐY\Ð]ð 	ðÜ˜¨T´4·>²>Ó3CÔFVÕ3VÓWˆØ×!Ñ!×sÐs¨¨f×.?Ñ.?Ð-@ÀÀ6Ç=Á=×CWÑCWÐX_ÐajÓCkÐlpÕCqÐBrÐ&sˆ÷ Ü—‘—‘  q¥	¨!¥Ó-ˆØ¤-Ô/Œ�Š´V·^±^Ð	CðIØJO×Q\ÑQ\ÓQ^ô	`ô 	×Ñ˜%Ö ñ ùô-eùò (\øô ×%Ñ%¤wÐ/ô Ü�A“�ûðús*   ÁG?Â*HÃ?=H Ä=4H ÈH;È&H6È6H;c               ó(   € V ^8„  d   QhRRRRRRRR/# ©r
   r   r   r9   r2   r3   r   rÐ   r   )r   s   "r   r   r   Ý   s*   € ÷ =ñ =¨ð =¸3ð =ÐH]ð =Ðbfñ =r   c           	     ón  a€ \        V4      pV'       d   \        V 4      MRpV'       d   \        W4      MRpV'       d   \        V4      '       g   R# \	        WRV.4      p\
        P                  ! 4       \        ,           p \        WW%^ V4      ;p'       dµ   VP                  4       '       d)   \        VP                  4       P                  R4      4      M	\        4       oVP                  R4      ;_uu_ 4       p	V	P                  RP                  V3R lV 4       4      4       RRR4       \!        WW„^ ,           RV^,           2V4       \/        YT4       R#   + '       g   i     L>; i  \"        P$                  \&        \(        3 d)   p
\*        P-                  RTR	,          T
4        Rp
?
LdRp
?
ii ; i)
aR  After a root container has stopped (so nothing writes any more) and before it is removed:
give its root-owned sandbox files (``mounts`` are ``(host_dir, container_path)``) to the host
user from a throwaway container of the same local image with the same volumes, and record
which, then strip what is left (the handback chown already cleared the bits it touched); each
step has its own time budget. The paths are recorded before any of them changes owner, so a
timeout mid-chown still leaves a complete record. Best-effort: a gone container, an image
without ``find`` or a timeout logs at debug.Nz--volumes-fromr¡   Úabr   c              3  óF   <"  € T F  qS9  g   K  VR ,           x € K  	  R# 5ir¼   r   )r[   r˜   Úknowns   & €r   r]   Ú*hand_back_sandbox_files.<locals>.<genexpr>ð   s   øé € Ð!M±U°Àu¹n¤) ! e§)¢)³Uùs   ƒ!�!rK   z#ownership handback of %s failed: %sr=   )r7   r0   rD   rP   rÍ   r´   rµ   rØ   r¦   Úis_fileÚsetÚ
read_bytesrO   ÚopenÚwriter¾   r¿   r   r   r    rC   r!   r"   rÞ   )r   r9   r2   ÚrecordÚidsr   r›   rœ   r¹   Úfhr&   rä   s   &&&        @r   Úhand_back_sandbox_filesrî   Ý   sI  ø€ ô ˜&Ó!€Fß'-Œ-˜
Ô
#°4€Cß14Œ8�JÔ-¸$€Dß”} T×*Ò*ÙÜ˜Ð-=¸|Ð,LÓM€FÜ�~Š~ÓÔ"2Õ2€HðRÜ˜*¨f¸A¸xÓHÐHˆ5ÖHØ=C¿^¹^×=MÒ=M”C˜×)Ñ)Ó+×1Ñ1°%Ó8Ô9ÔSVÓSXˆEØ—‘˜T×"Ô" bØ—‘˜Ÿ™Ô!M±UÓ!MÓMÔN÷ #ä�: u°Qµ°¸¸#¸a½&¸Ð.BÀHÔMô ˜Z°tÖ<÷ #×"ûô ×%Ñ%¤w´Ð9ô RÜ�‰Ð:¸LÈÕ<MÈq×QÑQûðRús7   Â+E, Â-AE, Ã8+EÄ#(E, ÅE)	Å$E, Å, F4ÆF/Æ/F4c               ó(   € V ^8„  d   QhRRRRRRRR/# rà   r   )r   s   "r   r   r   ÷   s*   € ÷ #ñ # cð #¸ð #ÐF[ð #Ð`dñ #r   c                ó0  € \        V4      pVe   VP                  4       '       g   R# \        P                  R8X  d   \	        W4      M/ pVf   R# V'       d   \        V4      '       g   VP                  RR7       R# . R	O\        OVNp\        P                  ! 4       \        ,           p \        VP                  4       P                  R4      4      p\        WW$\        P                   ! 4       V4      pT;'       g    .  U	u. uF  q™V9   g   K  V	NK  	  p
p	Ve   V
'       d   \#        WV
RV4      '       g   R# TP                  RR7       R# u up	i   \$        P&                  \(        3 d*   p\*        P-                  RTR,          T4        Rp?R# Rp?ii ; i)
a/  After a container mounts sandbox dirs an earlier teardown handed back: when it runs as root,
return the recorded paths to root (so git/ssh ownership checks pass again), then drop the
record. A container running as any other user keeps the handed-back owner and just drops the
record. Only recorded paths a fresh no-symlink walk of this container's sandbox mounts still
finds (outside every nested mount) are touched, so a symlinked directory or a real host dir now
bound inside is never chowned. A failed walk or chown keeps the record for the next container.Nr*   T)Ú
missing_okrÈ   r¡   z"ownership reclaim in %s failed: %sr=   )ÚexecrÅ   z-urÈ   )r7   ræ   r+   r,   rD   rP   ÚunlinkrÊ   r´   rµ   rØ   rç   rè   rO   r¦   r-   r.   r¿   r   r   r    r!   r"   )r   r9   r2   rë   r   r›   rœ   ÚrecordedÚownedr˜   r¹   r&   s   &&&         r   Úreclaim_sandbox_filesrö   ÷   sA  € ô ˜&Ó!€FØ‚~˜VŸ^™^×-Ò-ÙÜ14·±ÀÔ1HŒ8�JÔ-Èb€DØ‚|Ùß”} T×*Ò*Ø�‰ ˆÔ&ÙÚB¬)ÐB°\ÐB€FÜ�~Š~ÓÔ"2Õ2€HðÜ�v×(Ñ(Ó*×0Ñ0°Ó7Ó8ˆÜ�j¨&¼¿
º
»ÀhÓOˆØ!ŸK˜K R˜KÓ9™K�q°©=—�™KˆÐ9ØŠ=ŸU¬6°*ÀeÈUÐT\×+]Ò+]Ùð ‡M�M˜T€MÖ"ùò :øô ×%Ñ%¤wÐ/ô Ü�‰Ð9¸<ÈÕ;LÈaÔPÝûðús7   Â*AE ÄEÄEÄE Ä"E ÅE ÅFÅ,FÆF)ú-ez"PATH=/usr/sbin:/usr/bin:/sbin:/binr÷   zLD_PRELOAD=r÷   zLD_LIBRARY_PATH=z-wrŠ   )z
--cap-droprX   ú	--cap-addÚCHOWNrø   ÚDAC_OVERRIDErø   ÚFOWNERz--security-optzno-new-privilegesz--pids-limitÚ64z--labelzhermes-handback=1)N)2Ú__conditional_annotations__Ú__doc__Ú
__future__r   r?   Úloggingr-   r’   rË   r   r+   r´   Úpathlibr   Útypingr   Úhermes_constantsr   Útools.environments.baser   Ú tools.environments.remote_commonr   Ú	getLoggerÚ__name__r!   rØ   r6   rÊ   rÉ   r   Ú__annotations__r'   r0   r7   rD   rP   rb   ry   r…   r™   r¦   r¢   r¿   rÍ   r×   rç   rÎ   rÞ   rî   rö   )rý   s   @r   Ú<module>r	     sß   øðôõ6 #ã Û Û 	Û 	Û Û Û 
Û Ý Ý å 4Ý 3Ý 8à	×	Ò	˜8Ó	$€ð Ð Ø*€ò s€	òwÐ ð %'Ð �/Ó &õ(õVõKõ

õ]õ
`õ
wõlõ
uõ	8õ
õ"õ9ð%Ð ñ ›%€ˆxÓ ÷!õ:=÷4#r   