+
    	:i;  c                   sb   . ROt ^ RIH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t^ RIHt ^ RIHt ^ RI5 ^ RI5 ^ RI5  ]! ]R4       ]! ]P2                  ! 4       ^,          4      tR
 t ! R R]4      t ! R R ]P:                  4      tR#   ] d    R	]n         LSi ; i)AuditSocketReceiverThreadAuditRecordReceiver)str)objectN)
cmp_to_key)
get_config)Z*	AUDIT_EOEi(  c                 s   V P                   P                  R 8X  g   V P                  P                  R 8X  d   R# \        P                  V P                   P                  8X  d   \        P                  ! \        P
                  R\        : RV P                   : 24       \        P                  ! \        P
                  RV P                  P                  4       ,          4       ^ R IpVP                  ^ 4       R# )NFzBsetroubleshoot generated AVC, exiting to avoid recursion, context=z, AVC scontext=zaudit event
%sT)
ZscontextZtypeZtcontext
my_contextsyslogLOG_ERRaudit_eventZformatsysZexit)avcr      & =/usr/lib/python3.14/site-packages/setroubleshoot/avc_audit.py
verify_avcr   7   s    
||D CLL$5$5$=#,,+++fnn  BL  NQ  NZ  NZ  '[  	\fnn&73??;Q;Q;S&TU    c                   sx   a  ] tR t^Ft o RtRtR tR tR tR t	R t
R tR	 tR
 tRR ltRR ltR tR tRtV tR# )r   a[  
The audit system emits messages about a single event
independently. Thus one single auditable event may be composed
from one or more individual audit messages. Each audit message is
prefixed with a unique event id, which includes a timestamp. The
last audit message associated with an event is not marked in any
fashion. Audit messages for a specific event may arrive
interleaved with audit messages for other events. It is the job of
higher level software (this code) to assemble the audit messages
into events. The AuditEvent class is used for assembly. When a new
event id is seen a new AuditEvent object is created, then
every time an audit message arrives with that event id it is added
to that object. The AuditEvent object contains the timestamp
associated with the audit event as well as other data items useful
for processing and handling the event.

The audit system does not tell us when the last message belonging
to an event has been emitted so we have no explicit way of knowing
when the audit event has been fully assembled from its constituent
message parts. We use the heuristic if a sufficient length of
time has expired since we last saw a message for this event, then
it must be complete

Thus when audit events are created we place them in a cache where
they will reside until their time to live has expired at which
point we will assume they are complete and emit the event.

Events are expired in the flush_cache() method. The events
resident in the cache are sorted by their timestamps. A time
threshold is established. Any events in the cache older than the
time threshold are flushed from the cache as complete events.

When should flushes be performed? The moment when a new message is
added would seem a likely candidate moment to perform a sweep of
the cache. But this is costly and does not improve how quickly
events are expired. We could wait some interval of time (something
much greater than how long we expect it would take for messages
percolate) and this has good behavior, except for the following
case. Sometimes messages are emitted by audit in rapid
succession. If we swept the cache once a second then the cache may
have grown quite large. Since it is very likely that any given audit
event is complete by the time the next several events start
arriving we can optimize by tracking how many messages have
arrived since the last time we swept the cache.

The the heuristic for when to sweep the cache becomes:

If we've seen a sufficient number of messages then sweep -or- if
a sufficient length of time has elapsed then we sweep

Note that when audit messages are injected via log file scanning
elapsed wall clock time has no meaning relative to when to perform
the cache sweep. However, the timestamp for an event remains a
critical factor when deciding if an event is complete (have we
scanned far enough ahead such we're confident we won't see any
more messages for this event?). Thus the threshold for when to
expire an event from the cache during static log file scanning is
determined not by wall clock time but rather by the oldest
timestamp in the cache (e.g.there is enough spread between
timestamps in the cache its reasonable to assume the event is
complete). One might ask in the case of log file scanning why not
fill the cache until EOF is reached and then sweep the cache?
Because in log files it is not unusual to have thousands or tens
of thousands of events and the cache would grown needlessly
large. Because we have to deal with the real time case we already
have code to keep only the most recent events in the cache so we
might as well use that logic, keep the code paths the same and
minimize resource usage.
g{Gzt?c                s^    ^V n         ^ V n        / V n        . V n        V P	                  4        R# )i   N)
flush_sizeflush_countcacheeventsreset_statisticsself   &r   __init__ZAuditRecordReceiver.__init__   s+    
r   c                s,    \        V P                  4      # N)lenr   r   r   r   num_cached_eventsZ%AuditRecordReceiver.num_cached_events   s    4::r   c                s"    ^ V n         ^ V n        R# i    N)max_cache_lengthevent_countr   r   r   r   Z$AuditRecordReceiver.reset_statistics   s     !r   c                s\    \        4       pW P                  \        VP                  4      &   V# r   )Z
AuditEventr   r   event_idr   recordr
      && r   insert_new_eventZ$AuditRecordReceiver.insert_new_event   s$     l+6

3v'(r   c                s`    V P                   P                  \        VP                  4      R 4      # r   )r   Zgetr   r    )r   r"      &&r   get_event_from_recordZ)AuditRecordReceiver.get_event_from_record   s     zz~~c&//2D99r   c                s   \        V P                  P                  : R V: 24       V P                  V4      pVP                  R8X  d   V'       d   V P                  V4       R# Vf   V P                  V4      pVP                  V4       R# )z.add_record_to_cache(): EOEN)	log_debug	__class____name__r&   record_typeflush_eventr$   Z
add_recordr!   r#   r   add_record_to_cacheZ'AuditRecordReceiver.add_record_to_cache   so    DNN4K4KVTU008&  -//7Kv&r   c                sp    V ;P                   ^,          un         V P                  P                  ^ V4       R# )i   N)r   r   Zinsertr   r
   r%   r   
emit_eventZAuditRecordReceiver.emit_event   s'    A1k*r   c                sh    V P                  V4       V P                  \        VP                  4       R # r   )r/   r   r   r    r.   r%   r   r,   ZAuditRecordReceiver.flush_event   s%    $JJs;//01r   Nc                s  a  \        S P                  4      ^ 8X  d   R# \        S P                  4      S P                  8  d   \        S P                  4      S n        \        S P                  P	                  4       4      pV^ 8X  d0   V F'  pS P                  V,          pS P                  V4       K)  	  R# VP                  \        V 3R l4      R7       Vf6   S P                  VR,          ,          P                  S P                  ,
          pV F:  pS P                  V,          pVP                  V8  g   K)  S P                  V4       K<  	  R# )aD  Flush events from the cache if they are older than the threshold age.
If the threshold age is None then the threshold age is set to the age
of the newest event in the cache minus the cache time to live, in other
words anything in the cache which is older than the time to live relative
to the most current event is flushed.
Nc                 sz   < SP                   V ,          P                  SP                   V,          P                  8  # r   )r   	timestamp)ZaZbr   s   &&r   Z<lambda>Z1AuditRecordReceiver.flush_cache.<locals>.<lambda>   s'    4::a=3J3JTZZXY]MdMd3dr   )Zkeyi)
r   r   r   ZlistZkeysr,   Zsortr   r0   cache_time_to_live)r   threshold_ageZ	event_idsr    r
   s   f&   r   flush_cacheZAuditRecordReceiver.flush_cache   s     tzz?atzz?T222$'

OD!*+	 A%"jj2  - &  	:&def  JJy}5??$BYBYYM!H**X.K$$}4  - "r   c              #  s   "   V P                  V4       ^ V n        \        V P                  4      ^ 8  d!   V P                  P	                  4       pVx  K:  R# 5ir   )r3   r   r   r   pop)r   r2   r
   r#   r   flushZAuditRecordReceiver.flush   sG     '$++"++//+K #s   AAc              #  sF   "   V P                  ^ 4       F  pVx  K	  	  R# 5i)zsEmit every event in the cache irrespective of its
timestamp. This means we're done, nothing should remain buffered.N)r5   r.   r   r   closeZAuditRecordReceiver.close   s       ::a=K )s   !c              #  sd  "   V ;P                   ^,          un         VP                  R9   d   V P                  V4       V P                   V P                  8  d   V P	                  4        F  pVx  K	  	  \        V P                  4      ^ 8  d!   V P                  P                  4       pVx  K:  R# 5i)z9Accept a new audit record into the system for processing.N)ZAVCZAVC_PATHZSYSCALLZCWDZPATHr'   Z1400Z1107)r   r+   r-   r   r5   r   r   r4   r!   r#   r   feedZAuditRecordReceiver.feed   s      	A!ee$$V, doo-#zz|!!  , $++"++//+K #s   B.B0)r   r   r   r   r   r   r   )r*   
__module____qualname____firstlineno__Z__doc__r1   r   r   r   r$   r&   r-   r/   r,   r3   r5   r6   r7   __static_attributes____classdictcell__Z__classdict__   @r   r   r   F   sV     DP  
:
'+3 .D r   c                   sD   a  ] tR t^t o R tR tR tR tR tR t	Rt
V tR# )	r    c                s    \         P                  P                  V 4       Wn        W n        \        4       V n        \        R R\        4      V n	        V P                  4        ^V n        RV n        R# )auditretry_intervalFN)	threadingThreadr   queuereport_receiverr   record_receiverr   Zintr@   get_socket_pathstimeout_intervalhas_audit_eoe)r   rC   rD   s   &&&r   r   Z"AuditSocketReceiverThread.__init__   sZ    !!$'
.24(2BCH !"r   c                s    . V n         \        R R4      pV P                   P                  V4       \        R R4      pV P                   P                  V4       R# )r?   Ztext_protocol_socket_pathZbinary_protocol_socket_pathN)audit_socket_pathsr   Zappend)r   audit_socket_pathr   r   rF   Z*AuditSocketReceiverThread.get_socket_paths  sP    "$&w0KL&&'89&w0MN&&'89r   c           	     s     V P                    EF#  V n        V P                  f   K   \        V P                  4      p\        V4      V n        \
        P                  ! \
        P                  \
        P                  4      V n	        \        P                  ! V P                  P                  4       \        P                  \        P                  4       V P                  P                  V P                  4       V P                  P                  4       V n        \#        RV P                  ,          4        R# 	  \#        RRP)                  V P                   4      V P*                  3,          4       \.        P0                  ! V P*                  4       EK    \
        P$                   d8   p\'        T4      w  r4\#        RT P                  : RT: R24        Rp?EK  Rp?ii ; i  \
        P$                   d@   p\'        T4      w  r4\#        RT P                  Y@P*                  3,          4        Rp?LRp?i\,         d<   p\#        RT P                  T^,          T P*                  3,          4        Rp?ELRp?ii ; i)	TNzaudit socket (%s) connectedzattempt to open audit socket (z) failed, error='Z'z:could not open any audit sockets (%s), retry in %d secondsz, z9audit socket (%s) failed, error='%s', retry in %d seconds)rI   rJ   Zderive_record_formatZAuditRecordReaderrecord_readerSocketsocketZAF_UNIXZSOCK_STREAMaudit_socketfcntlfilenoZF_SETFDZ
FD_CLOEXECconnectZmakefileaudit_socket_fdr(   ZerrorZget_error_from_socket_exceptionZjoinr@   ZOSErrortimeZsleep)r   Zrecord_formateZerrnoZstrerrors   &    r   rQ   Z!AuditSocketReceiverThread.connect  s'   M.2.E.ED*--9C,@AWAW,XM1B=1QD.06fnnfN`N`0aD-!KK(9(9(@(@(BEMMSXScScd --55d6L6LM373D3D3M3M3OD0%&CdF\F\&\]" /F VZ^ZcZcdhd{d{Z|  C  R  R  ZS  S  T JJt**+  &|| C.Ma.POE%`d`v`v  yA  'B  C  CC << Q"A!"DUY]YoYoqy  |O  |O  YP  P  Q  Q MUY]YoYoqrstquw{  xK  xK  YL  L  M  MMsY    G  D	F2G  59G  G&+GG  GG   I855H//I8<I8=0I33I8c                s    \        WW4V4      pVP                  4        V P                  P                  V4       F  pV P	                  V4       K  	  R# )z"called to enter a new audit recordN)ZAuditRecordZaudispd_rectifyrE   r7   new_audit_event_handler)r   r+   r    	body_textfieldsline_numberZaudit_recordr
   s   &&&&&&  r   new_audit_record_handlerZ2AuditSocketReceiverThread.new_audit_record_handler1  sH     #;)[Y$$&//44\BK((5 Cr   c                s.   VP                  4       '       d   VP                  4       '       gg   VP                  4       ^ 8  dP   \        V4      pV F<  p\	        V4      '       g   K  V P
                  P                  W0P                  34       K>  	  R# R# R# R# r   )Zis_avcZ
is_grantedZnum_recordsZcompute_avcsr   rC   ZputrD   )r   r
   Zavcsr   s   &&  r   rU   Z1AuditSocketReceiverThread.new_audit_event_handler9  ss    (>(>(@(@[E\E\E^abEb,Dc??JJNNC)=)=#>?  Fc(@r   c           
     s   V P                  4        V P                  p \        P                  ! V P                  .. . V4      w  r#p V P                  V9   d   ^ RIpVP                  V P                  P                  4       R4      pVR8X  d   \        R4       V P                  4        K  \        RV P                  P                  4       ,          4       V P                  '       g   V P                  pV P                  P                  V4       F*  w  rxrpVR8X  d
   R V n        RpV P                  WxWV4       K,  	  EK   V P                  P                  \         P                   ! 4       V P                  ,
          4       F  pV P#                  V4       K  	  V P                  P                  4       ^ 8X  d   RpEK  EK    \$         dH   p\        RT P&                  P(                  ,          4       \*        P,                  ! 4         Rp?EK  Rp?i\.         dH   p\        RT P&                  P(                  ,          4       \*        P,                  ! 4         Rp?EK;  Rp?i\0         ds   p^ RIp\5        TP7                  4       4       \8        P8                  ! \8        P:                  R	TP&                  P(                  : R
\=        T4      : 24        Rp?R# Rp?ii ; i)TNi   Z zaudit socket connection droppedzcached audit event count = %dr'   z!KeyboardInterrupt exception in %szSystemExit exception in %sz
exception z: )rQ   rG   selectrN   osZreadrR   rP   r(   rE   r   rH   rK   r7   rY   r5   rS   rU   ZKeyboardInterruptr)   r*   _threadZinterrupt_mainZ
SystemExitZ	Exception	tracebackZsyslog_traceZ
format_excr   r	   r   )r   ZtimeoutZinListZoutListZerrListr[   Znew_datar+   r    rV   rW   rX   r
   rT   r]   s   &              r   runZAuditSocketReceiverThread.run@  s   '''-}}d6G6G5H"bRY'Z$FW#$$.!wwt';';'B'B'DdKH2~!"CD!"ATEYEYEkEkEm"no#111&*&;&;GW[WiWiWnWnowWxS[I{*e359 2*. 99+QZdop	 Xy (,';';'A'A$))+PTPePeBe'f44[A (g++==?1D"& E % )=@W@WWX&&(( )69P9PPQ&&((  Y1134fnnAKKDXDXZ]^_Z`.ab	sL   A!F; )BF; =A8F; ;K;HKK;IK%K&A'KK)rN   rR   rJ   rI   rH   rC   rK   rE   rD   r@   rG   N)r*   r8   r9   r:   r   rF   rQ   rY   rU   r^   r;   r<   r=   r>   r   r    r       s)     	#:,:6@) )r   )r    r   r   )Z__all__Zbuiltinsr   r   r   r?   rZ   ZselinuxrM   rL   rO   r\   rA   rS   Z	functoolsr   Zsetroubleshoot.configr   Zsetroubleshoot.errcodeZsetroubleshoot.utilZsetroubleshoot.audit_dataZgetattrZAttributeErrorr   Z
AvcContextZgetconr   r   r   rB   r    ) r   r   <module>r_      s   (              , $ ! 'E; (+,

s& spk	 0 0 k_  EOs   	B B.-B.