Struct es_message_t

Source
#[repr(C)]
pub struct es_message_t { pub version: u32, pub time: timespec, pub mach_time: u64, pub deadline: u64, pub process: ShouldNotBeNull<es_process_t>, pub seq_num: u64, pub action_type: es_action_type_t, pub action: es_message_t_anon_0, pub event_type: es_event_type_t, pub event: es_events_t, pub thread: *mut es_thread_t, pub global_seq_num: u64, /* private fields */ }
Available on macOS only.
Expand description

This is the top level datatype that encodes information sent from the ES subsystem to its clients. Each security event being processed by the ES subsystem will be encoded in an es_message_t. A message can be an authorization request or a notification of an event that has already taken place.

For events that can be authorized there are unique NOTIFY and AUTH event types for the same event data, eg: event.exec is the correct union label for both ES_EVENT_TYPE_AUTH_EXEC and ES_EVENT_TYPE_NOTIFY_EXEC event types.

For fields marked only available in specific message versions, all access must be guarded at runtime by checking the value of the message version field, e.g.

if msg.version >= 2 {
    acl = unsafe { msg.event.create.acl };
}

Fields using Mach time are in the resolution matching the ES client’s architecture. This means they can be compared to mach_absolute_time() and converted to nanoseconds with the help of mach_timebase_info(). Further note that on Apple silicon, x86_64 clients running under Rosetta 2 will see Mach times in a different resolution than native arm64 clients. For more information on differences regarding Mach time on Apple silicon and Intel-based Mac computers, see “Addressing Architectural Differences in Your macOS Code”: https://developer.apple.com/documentation/apple_silicon/addressing_architectural_differences_in_your_macos_code

§Rust implementation notes

RefEncode is currently implemented with the encoding left unknown explicitly. If es_message_t needs to be encoded for Objective C messages, this will require changes.

§A note on userspace events

Before macOS 13.0 almost all ES events were created by xnu (the macOS kernel). Such events are mandatory. If no es_event_setuid_t event is emitted then no setuid took place. This is a security guarantee. Most events added in macOS 13 and 14 are emitted by userspace binaries and frameworks. ES still guarantees that if an event was not emitted by that binary or framework then it did not happen, but this is not quite the same guarantee.

Consider es_event_su_t: This event is created by the su binary first shipped in macOS 14.0, but it’s entirely possible for a user to install (or compile) a different su! ES only guarantees that the platform binary shipped with macOS emits es_event_su_t events. As such es_event_su_t does not provide the same security guarantee that es_event_setuid_t does.

When a user invokes the platform su binary ES will emit both es_event_su_t and es_event_setuid_t events. When a user compiles their own su binary from source and executes it:

  • ES will emit an es_event_setuid_t event.
  • ES will NOT emit an es_event_su_t.

Userspace events are inherently discretionary. It is at the users discretion as to whether they use the builtin binaries/frameworks or not. Kernel events are mandatory. There is no setuid syscall that ES does not interdict.

The following events are created by userspace binaries or frameworks:

  • [ES_EVENT_TYPE_AUTH_FILE_PROVIDER_MATERIALIZE]
  • [ES_EVENT_TYPE_NOTIFY_FILE_PROVIDER_MATERIALIZE]
  • [ES_EVENT_TYPE_AUTH_FILE_PROVIDER_UPDATE]
  • [ES_EVENT_TYPE_NOTIFY_FILE_PROVIDER_UPDATE]
  • [ES_EVENT_TYPE_NOTIFY_AUTHENTICATION]
  • [ES_EVENT_TYPE_NOTIFY_XP_MALWARE_DETECTED]
  • [ES_EVENT_TYPE_NOTIFY_XP_MALWARE_REMEDIATED]
  • [ES_EVENT_TYPE_NOTIFY_LW_SESSION_LOGIN]
  • [ES_EVENT_TYPE_NOTIFY_LW_SESSION_LOGOUT]
  • [ES_EVENT_TYPE_NOTIFY_LW_SESSION_LOCK]
  • [ES_EVENT_TYPE_NOTIFY_LW_SESSION_UNLOCK]
  • [ES_EVENT_TYPE_NOTIFY_SCREENSHARING_ATTACH]
  • [ES_EVENT_TYPE_NOTIFY_SCREENSHARING_DETACH]
  • [ES_EVENT_TYPE_NOTIFY_OPENSSH_LOGIN]
  • [ES_EVENT_TYPE_NOTIFY_OPENSSH_LOGOUT]
  • [ES_EVENT_TYPE_NOTIFY_LOGIN_LOGIN]
  • [ES_EVENT_TYPE_NOTIFY_LOGIN_LOGOUT]
  • [ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_ADD]
  • [ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_REMOVE]
  • [ES_EVENT_TYPE_NOTIFY_PROFILE_ADD]
  • [ES_EVENT_TYPE_NOTIFY_PROFILE_REMOVE]
  • [ES_EVENT_TYPE_NOTIFY_SU]
  • [ES_EVENT_TYPE_NOTIFY_AUTHORIZATION_PETITION]
  • [ES_EVENT_TYPE_NOTIFY_AUTHORIZATION_JUDGEMENT]
  • [ES_EVENT_TYPE_NOTIFY_SUDO]
  • [ES_EVENT_TYPE_NOTIFY_OD_GROUP_ADD]
  • [ES_EVENT_TYPE_NOTIFY_OD_GROUP_REMOVE]
  • [ES_EVENT_TYPE_NOTIFY_OD_GROUP_SET]
  • [ES_EVENT_TYPE_NOTIFY_OD_MODIFY_PASSWORD]
  • [ES_EVENT_TYPE_NOTIFY_OD_DISABLE_USER]
  • [ES_EVENT_TYPE_NOTIFY_OD_ENABLE_USER]
  • [ES_EVENT_TYPE_NOTIFY_OD_ATTRIBUTE_VALUE_ADD]
  • [ES_EVENT_TYPE_NOTIFY_OD_ATTRIBUTE_VALUE_REMOVE]
  • [ES_EVENT_TYPE_NOTIFY_OD_ATTRIBUTE_SET]
  • [ES_EVENT_TYPE_NOTIFY_OD_CREATE_USER]
  • [ES_EVENT_TYPE_NOTIFY_OD_CREATE_GROUP]
  • [ES_EVENT_TYPE_NOTIFY_OD_DELETE_USER]
  • [ES_EVENT_TYPE_NOTIFY_OD_DELETE_GROUP]

Fields§

§version: u32

Indicates the message version; some fields are not available and must not be accessed unless the message version is equal to or higher than the message version at which the field was introduced.

§time: timespec

The time at which the event was generated

§mach_time: u64

The Mach absolute time at which the event was generated

§deadline: u64

The Mach absolute time before which an auth event must be responded to. If a client fails to respond to auth events prior to the deadline, the client will be killed. Each message can contain its own unique deadline, and some deadlines can vary substantially. Clients must take care to inspect the deadline value of each message to know how much time is allotted for processing.

§process: ShouldNotBeNull<es_process_t>

Describes the process that took the action

§seq_num: u64

Per-client, per-event-type sequence number that can be inspected to detect whether the kernel had to drop events for this client. When no events are dropped for this client, seq_num increments by 1 for every message of that event type. When events have been dropped, the difference between the last seen sequence number of that event type plus 1 and seq_num of the received message indicates the number of events that had to be dropped. Dropped events generally indicate that more events were generated in the kernel than the client was able to handle.

See global_seq_num.

Field available only if message version >= 2.

§action_type: es_action_type_t

Indicates if the action field is an auth or notify action

§action: es_message_t_anon_0

For auth events, contains the opaque auth ID that must be supplied when responding to the event. For notify events, describes the result of the action.

§event_type: es_event_type_t

Indicates which event struct is defined in the event union

§event: es_events_t

Contains data specific to the event type

§thread: *mut es_thread_t
Available on crate feature macos_11_0_0 only.

Describes the thread that took the action. May be NULL when thread is not applicable, for example for trace events that describe the traced process calling ptrace(PT_TRACE_ME) or for cs invalidated events that are a result of another process calling csops(CS_OPS_MARKINVALID).

Field available only if message version >= 4.

§global_seq_num: u64
Available on crate feature macos_11_0_0 only.

Per-client sequence number that can be inspected to detect whether the kernel had to drop events for this client. When no events are dropped for this client, global_seq_num increments by 1 for every message. When events have been dropped, the difference between the last seen global sequence number and the global_seq_num of the received message indicates the number of events that had to be dropped. Dropped events generally indicate that more events were generated in the kernel than the client was able to handle.

See also: seq_num.

Field available only if message version >= 4.

Implementations§

Source§

impl es_message_t

Accessors for ShouldNotBeNull fields

Source

pub unsafe fn process(&self) -> &es_process_t

Gives a references to the field while checking for null.

§Safety

See ShouldNotBeNull safety requirements.

Source§

impl es_message_t

Accessors for *mut and *const fields

Source

pub unsafe fn thread(&self) -> Option<&es_thread_t>

Helper to avoid the is_null() + deref every time.

§Safety

The pointer must be valid (aligned & initialized) for a value of the expected type.

Trait Implementations§

Source§

impl RefEncode for es_message_t

Source§

const ENCODING_REF: Encoding

The Objective-C type-encoding for a reference of this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> AutoreleaseSafe for T
where T: ?Sized,