1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright (C) 2019 - Will Glozer. All rights reserved.

use std::fmt;
use std::os::raw::{c_char, c_int};
use super::conn::cn_msg;

pub const PROC_CN_MCAST_LISTEN: u32 = 1;
pub const PROC_CN_MCAST_IGNORE: u32 = 2;

#[repr(C, packed)]
#[derive(Copy, Clone, Debug)]
pub struct cn_proc_event {
    pub cn:    cn_msg,
    pub event: proc_event,
}

#[repr(C)]
#[derive(Clone, Copy, Default)]
pub struct proc_event {
    pub what:         what,
    pub cpu:          u32,
    pub timestamp_ns: u64,
    pub event_data:   event_data,
}

#[repr(u32)]
#[derive(Clone, Copy, Debug)]
pub enum what {
    PROC_EVENT_NONE     = 0x00000000,
    PROC_EVENT_FORK     = 0x00000001,
    PROC_EVENT_EXEC     = 0x00000002,
    PROC_EVENT_UID      = 0x00000004,
    PROC_EVENT_GID      = 0x00000040,
    PROC_EVENT_SID      = 0x00000080,
    PROC_EVENT_PTRACE   = 0x00000100,
    PROC_EVENT_COMM     = 0x00000200,
    PROC_EVENT_COREDUMP = 0x40000000,
    PROC_EVENT_EXIT     = 0x80000000,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub union event_data {
    pub ack:      ack,
    pub fork:     fork_proc_event,
    pub exec:     exec_proc_event,
    pub uid:      uid_proc_event,
    pub gid:      gid_proc_event,
    pub sid:      sid_proc_event,
    pub ptrace:   ptrace_proc_event,
    pub comm:     comm_proc_event,
    pub coredump: coredump_proc_event,
    pub exit:     exit_proc_event,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct ack {
    pub err: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct fork_proc_event {
    pub parent_pid:  u32,
    pub parent_tgid: u32,
    pub child_pid:   u32,
    pub child_tgid:  u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct exec_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct uid_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub ruid:         u32,
    pub euid:         u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct gid_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub rgid:         u32,
    pub egid:         u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct sid_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct ptrace_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub tracer_pid:   u32,
    pub tracer_tgid:  u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct comm_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub comm:         [c_char; 16],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct coredump_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct exit_proc_event {
    pub process_pid:  u32,
    pub process_tgid: u32,
    pub exit_code:    u32,
    pub exit_signal:  u32,
}

impl Default for what {
    fn default() -> Self {
        what::PROC_EVENT_NONE
    }
}

impl Default for event_data {
    fn default() -> Self {
        Self { ack: ack { err: 0 } }
    }
}

impl fmt::Debug for proc_event {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let event_data = unsafe {
            let data = &self.event_data;
            match self.what {
                what::PROC_EVENT_NONE     => &"NONE"        as &dyn fmt::Debug,
                what::PROC_EVENT_FORK     => &data.fork     as &dyn fmt::Debug,
                what::PROC_EVENT_EXEC     => &data.exec     as &dyn fmt::Debug,
                what::PROC_EVENT_UID      => &data.uid      as &dyn fmt::Debug,
                what::PROC_EVENT_GID      => &data.gid      as &dyn fmt::Debug,
                what::PROC_EVENT_SID      => &data.sid      as &dyn fmt::Debug,
                what::PROC_EVENT_PTRACE   => &data.ptrace   as &dyn fmt::Debug,
                what::PROC_EVENT_COMM     => &data.comm     as &dyn fmt::Debug,
                what::PROC_EVENT_COREDUMP => &data.coredump as &dyn fmt::Debug,
                what::PROC_EVENT_EXIT     => &data.exit     as &dyn fmt::Debug,
            }
        };

        f.debug_struct("proc_event")
            .field("what",         &self.what)
            .field("cpu",          &self.cpu)
            .field("timestamp_ns", &self.timestamp_ns)
            .field("event_data",   event_data)
            .finish()
    }
}