diff options
Diffstat (limited to 'src/proc_connector.c')
| -rw-r--r-- | src/proc_connector.c | 758 |
1 files changed, 758 insertions, 0 deletions
diff --git a/src/proc_connector.c b/src/proc_connector.c new file mode 100644 index 0000000..f771ecf --- /dev/null +++ b/src/proc_connector.c @@ -0,0 +1,758 @@ + +#include <string.h> +#include <stdbool.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <stdio.h> +#include <errno.h> +#include <sys/socket.h> +#include <sys/stat.h> + +#include <linux/cn_proc.h> +#include <linux/netlink.h> +#include <linux/connector.h> + +#include "net.h" +#include "json.h" +#include "error.h" +#include "output.h" +#include "md5.h" +#include "sha256.h" +#include "base64.h" +#include "proc.h" +#include "agent_context.h" +#include "proc_ledger.h" +#include "time_common.h" +#include "string_common.h" +#include "proc_connector.h" + +extern unsigned long maxsize; + + +static void handle_proc_connector_message(struct cn_msg *cn_message, agent_context_t *ctx) { + struct proc_event *event; + json_t json = {0}; + pid_t process; + struct proc_ledger_entry *entry; + + event = (struct proc_event *)cn_message->data; + + switch (event->what) { + case PROC_EVENT_NONE: + break; + + case PROC_EVENT_FORK: + pid_t child = event->event_data.fork.child_pid; + + entry = proc_ledger_entry_create(child, ctx); + if (entry) { + proc_ledger_add(ctx->proc_ledger, entry); + } + json = handle_PROC_EVENT_FORK(event, ctx); + break; + + case PROC_EVENT_EXEC: + process = event->event_data.exec.process_pid; + entry = proc_ledger_entry_create(process, ctx); + + if (entry) { + proc_ledger_replace(ctx->proc_ledger, entry); + + json = handle_PROC_EVENT_EXEC(event, ctx); + + json_t environment = handle_PROC_EVENT_EXEC_environment(event, ctx); + if (environment.data) { + output(json_get(&environment)); + json_free(&environment); + } + } + break; + + case PROC_EVENT_EXIT: + process = event->event_data.exit.process_pid; + json = handle_PROC_EVENT_EXIT(event, ctx); + proc_ledger_remove(ctx->proc_ledger, process); + break; + + case PROC_EVENT_UID: + // update ledger with new UIDs + entry = proc_ledger_find(ctx->proc_ledger, event->event_data.id.process_pid); + if (entry) { + int old_ruid = entry->uid; + int old_euid = entry->euid; + entry->uid = event->event_data.id.r.ruid; + entry->euid = event->event_data.id.e.euid; + json = handle_PROC_EVENT_UID(event, ctx, old_ruid, old_euid); + } else { + json = handle_PROC_EVENT_UID(event, ctx, -1, -1); + } + break; + + case PROC_EVENT_GID: + // update ledger with new GIDs + entry = proc_ledger_find(ctx->proc_ledger, event->event_data.id.process_pid); + if (entry) { + int old_rgid = entry->gid; + int old_egid = entry->egid; + entry->gid = event->event_data.id.r.rgid; + entry->egid = event->event_data.id.e.egid; + json = handle_PROC_EVENT_GID(event, ctx, old_rgid, old_egid); + } else { + json = handle_PROC_EVENT_GID(event, ctx, -1, -1); + } + break; + + case PROC_EVENT_PTRACE: + json = handle_PROC_EVENT_PTRACE(event, ctx); + break; + + case PROC_EVENT_SID: + json = handle_PROC_EVENT_SID(event, ctx); + break; + + case PROC_EVENT_COMM: + // update ledger with new comm + char *old_comm = NULL; + entry = proc_ledger_find(ctx->proc_ledger, event->event_data.comm.process_pid); + if (entry) { + old_comm = strdup(entry->comm); + strncpy(entry->comm, event->event_data.comm.comm, sizeof(entry->comm) - 1); + entry->comm[sizeof(entry->comm) - 1] = '\0'; + } + + json = handle_PROC_EVENT_COMM(event, ctx, old_comm); + if (old_comm) { + free(old_comm); + } + + break; + + case PROC_EVENT_COREDUMP: + json = handle_PROC_EVENT_COREDUMP(event, ctx); + break; + + default: + json = handle_PROC_EVENT_UNKNOWN(event, ctx); + break; + } + + /* If we have data to output, deal with it. */ + if (json.data) { + output(json_get(&json)); + json_free(&json); + } +} + +sock_t setup_proc_connector(void) { + int err; + sock_t proc_connector; + struct sockaddr_nl nl_userland; + enum proc_cn_mcast_op *mcop_msg; + struct cn_msg *cn_message; + char buf[1024] = {0}; + struct nlmsghdr *nl_header; + + proc_connector = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + if (proc_connector == -1) { + error("error creating proc_connector socket: %s", strerror(errno)); + return -1; + } + + nl_userland.nl_family = AF_NETLINK; + nl_userland.nl_groups = CN_IDX_PROC; + nl_userland.nl_pid = getpid(); + + err = bind(proc_connector, (struct sockaddr *)&nl_userland, sizeof(nl_userland)); + if (err == -1) { + error("error binding proc_connector socket: %s", strerror(errno)); + return -1; + } + + nl_header = (struct nlmsghdr *)buf; + cn_message = (struct cn_msg *)NLMSG_DATA(nl_header); + mcop_msg = (enum proc_cn_mcast_op *)&cn_message->data[0]; + *mcop_msg = PROC_CN_MCAST_LISTEN; + + cn_message->id.idx = CN_IDX_PROC; + cn_message->id.val = CN_VAL_PROC; + cn_message->seq = 0; + cn_message->ack = 0; + cn_message->len = sizeof(enum proc_cn_mcast_op); + + nl_header->nlmsg_len = NLMSG_LENGTH(sizeof(struct cn_msg) + sizeof(enum proc_cn_mcast_op)); + nl_header->nlmsg_type = NLMSG_DONE; + nl_header->nlmsg_flags = 0; + nl_header->nlmsg_seq = 0; + nl_header->nlmsg_pid = getpid(); + + err = send(proc_connector, nl_header, nl_header->nlmsg_len, 0); + if (err != nl_header->nlmsg_len) { + error("send: %s", strerror(errno)); + close(proc_connector); + return -1; + } + + return proc_connector; +} + +void select_proc_connector(sock_t proc_connector, agent_context_t *ctx) { + int recv_length; + socklen_t nl_kernel_len; + struct nlmsghdr *nlh; + struct cn_msg *cn_message; + struct sockaddr_nl nl_kernel; + char buf[1024] = {0}; + + nl_kernel_len = sizeof(nl_kernel); + + recv_length = recvfrom(proc_connector, + buf, + sizeof(buf), + 0, + (struct sockaddr *)&nl_kernel, + &nl_kernel_len); + nlh = (struct nlmsghdr *)buf; + + if ((recv_length < 1) || (nl_kernel.nl_pid != 0)) { + return; + } + + while (NLMSG_OK(nlh, recv_length)) { + cn_message = NLMSG_DATA(nlh); + + if ((nlh->nlmsg_type == NLMSG_NOOP) || + (nlh->nlmsg_type == NLMSG_ERROR)) { + continue; + } + + if (nlh->nlmsg_type == NLMSG_OVERRUN) { + break; + } + + handle_proc_connector_message(cn_message, ctx); + + if (nlh->nlmsg_type == NLMSG_DONE) { + break; + } else { + nlh = NLMSG_NEXT(nlh, recv_length); + } + } +} + +static inline const char *safe_exe_path(struct proc_ledger_entry *entry) { + if (entry && entry->exe[0]) { + return entry->exe; + } + return "UNKNOWN"; +} + +/* handle_PROC_EVENT_FORK() - Handle PROC_EVENT_FORK events. + * + * The following are available for this event: + * - pid_t parent_pid + * - pid_t parent_tgid + * - pid_t child_pid + * - pid_t child_tgid + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * + * Returns: + * json_t containing serialized JSON object describing this event. + * + * TODO: Deal with parent_pid and child_pid being the same somehow (see below) + */ +json_t handle_PROC_EVENT_FORK(struct proc_event *event, agent_context_t *ctx) { + pid_t parent_pid = event->event_data.fork.parent_pid; + pid_t parent_tgid = event->event_data.fork.parent_tgid; + pid_t child_pid = event->event_data.fork.child_pid; + pid_t child_tgid = event->event_data.fork.child_tgid; + + struct proc_ledger_entry *parent_entry = proc_ledger_find(ctx->proc_ledger, parent_pid); + if (!parent_entry) { + json_t empty = {0}; + return empty; + } + + struct proc_ledger_entry *child_entry = proc_ledger_entry_create(child_pid, ctx); + if (child_entry && parent_entry) { + memcpy(child_entry, parent_entry, sizeof(struct proc_ledger_entry)); + child_entry->pid = child_pid; + child_entry->tgid = child_tgid; + snprintf(child_entry->comm, sizeof(child_entry->comm), "%s", parent_entry->comm); + proc_ledger_add(ctx->proc_ledger, child_entry); + } + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "fork"); + json_add_int(&buf, "parent_pid", parent_pid); + json_add_int(&buf, "parent_tgid", parent_tgid); + json_add_int(&buf, "child_pid", child_pid); + json_add_int(&buf, "child_tgid", child_tgid); + json_add_string(&buf, "parent_exepath", parent_entry->exe); + json_add_string(&buf, "parent_comm", parent_entry->comm); + json_add_string(&buf, "cmdline", parent_entry->cmdline); + bool deleted = endswith(parent_entry->exe, " (deleted)"); + json_add_bool(&buf, "deleted", deleted); + json_add_int(&buf, "uid", parent_entry->uid); + json_add_int(&buf, "euid", parent_entry->euid); + json_add_int(&buf, "gid", parent_entry->gid); + json_add_int(&buf, "egid", parent_entry->egid); + + // TODO is parent_entry correct, or child_entry? + struct hash_entry *hentry = hash_ledger_find(ctx->hash_ledger, parent_entry->exe); + if (hentry) { + if (hentry->md5[0]) { + json_add_string(&buf, "md5", hentry->md5); + } + if (hentry->sha256[0]) { + json_add_string(&buf, "sha256", hentry->sha256); + } + + json_add_double(&buf, "entropy", hentry->entropy); + } + + json_end_object(&buf); + + return buf; +} + + +/* handle_PROC_EVENT_EXEC() - Handle PROC_EVENT_EXEC events. + * + * The following are available for this event: + * - pid_t process_pid + * - pid_t process_tgid + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * + * Returns: + * json_t containing serialized JSON object describing this event. + */ +json_t handle_PROC_EVENT_EXEC(struct proc_event *event, agent_context_t *ctx) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.exec.process_pid); + if (!entry) { + json_t empty = {0}; + return empty; + } + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "exec"); + json_add_int(&buf, "pid", entry->pid); + json_add_int(&buf, "tgid", entry->tgid); + json_add_int(&buf, "uid", entry->uid); + json_add_int(&buf, "euid", entry->euid); + json_add_int(&buf, "gid", entry->gid); + json_add_int(&buf, "egid", entry->egid); + json_add_string(&buf, "exepath", entry->exe); + json_add_string(&buf, "cmdline", entry->cmdline); + json_add_string_or_null(&buf, "cwd", entry->cwd); + + struct hash_entry *hentry = hash_ledger_find(ctx->hash_ledger, entry->exe); + if (hentry) { + json_add_string_or_null(&buf, "md5", hentry->md5); + json_add_string_or_null(&buf, "sha256", hentry->sha256); + json_add_double(&buf, "entropy", hentry->entropy); + } + + json_end_object(&buf); + + return buf; +} + +/* handle_PROC_EVENT_EXEC_environment() - Grab the environment from + * PROC_EVENT_EXEC events. + * + * This is called after handle_PROC_EVENT_EXEC() to attempt to grab + * the environment from /proc/X/environ for a newly-executed + * process. This information may be useful from a forensics + * standpoint, and possibly to detect malicious activity. + * + * Since an environment can contain anything, it is base64 encoded so + * it doesn't break our JSON formatting. + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * + * Returns: + * json_t containing serialized JSON object describing this event. + */ +json_t handle_PROC_EVENT_EXEC_environment(struct proc_event *event, agent_context_t *ctx) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.exec.process_pid); + if (!entry) { + json_t empty = {0}; + return empty; + } + + pid_t pid = event->event_data.exec.process_pid; + + char *environment = proc_environ(pid); + if (!environment) { + json_t empty = {0}; + return empty; + } + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "environment"); + json_add_int(&buf, "pid", entry->pid); + json_add_int(&buf, "uid", entry->uid); + json_add_int(&buf, "euid", entry->euid); + json_add_int(&buf, "gid", entry->gid); + json_add_int(&buf, "egid", entry->egid); + json_add_string(&buf, "exepath", entry->exe); + json_add_string(&buf, "environment", environment); + + json_end_object(&buf); + + free(environment); + return buf; +} + +/* handle_PROC_EVENT_EXIT() - Handle PROC_EVENT_EXIT events. + * + * The following are available for this event: + * - pid_t process_pid + * - pid_t process_tgid + * - u32 exit_code + * - u32 exit_signal + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * + * Returns: + * json_t containing serialized JSON object describing this event. + */ +json_t handle_PROC_EVENT_EXIT(struct proc_event *event, agent_context_t *ctx) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.exit.process_pid); + if (!entry) { + json_t empty = {0}; + return empty; + } + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "exit"); + json_add_int(&buf, "pid", event->event_data.exit.process_pid); + json_add_int(&buf, "tgid", event->event_data.exit.process_tgid); + json_add_int(&buf, "exitcode", event->event_data.exit.exit_code); + json_add_int(&buf, "signal", event->event_data.exit.exit_signal); + json_add_string(&buf, "exepath", safe_exe_path(entry)); + + json_end_object(&buf); + + return buf; +} + +/* handle_PROC_EVENT_UID() - Handle PROC_EVENT_UID events. + * handle_PROC_EVENT_GID() - Handle PROC_EVENT_GID events. + * + * The following are availabie for this event: + * - pid_t process_ppid + * - pid_t process_tgid + * - union { u32 ruid; u32 rgid } r + * - union { u32 euid; u32 egid } e + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * old_ruid - old real uid + * old_euid - old effective uid + * + * Returns: + * json_t containing serialized JSON object describing this event + * + * Note: + * The handle_PROC_EVENT_UID and handle_PROC_EVENT_GID functions + * are nearly identical. If no record of the old ruid/euid of the + * process exists, -1 will be displayed + */ + +json_t handle_PROC_EVENT_UID(struct proc_event *event, agent_context_t *ctx, int old_ruid, int old_euid) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.id.process_pid); + if (!entry) { + json_t empty = {0}; + return empty; + } + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "uid"); + json_add_int(&buf, "pid", entry->pid); + json_add_int(&buf, "tgid", entry->tgid); + json_add_int(&buf, "old_ruid", old_ruid); + json_add_int(&buf, "new_ruid", event->event_data.id.r.ruid); + json_add_int(&buf, "old_euid", old_euid); + json_add_int(&buf, "new_euid", event->event_data.id.e.euid); + json_add_string(&buf, "exepath", entry->exe); + + json_end_object(&buf); + + return buf; +} + +json_t handle_PROC_EVENT_GID(struct proc_event *event, agent_context_t *ctx, int old_rgid, int old_egid) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.id.process_pid); + if (!entry) { + json_t empty = {0}; + return empty; + } + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "gid"); + json_add_int(&buf, "pid", entry->pid); + json_add_int(&buf, "tgid", entry->tgid); + json_add_int(&buf, "old_rgid", old_rgid); + json_add_int(&buf, "new_rgid", event->event_data.id.r.rgid); + json_add_int(&buf, "old_egid", old_egid); + json_add_int(&buf, "new_egid", event->event_data.id.e.egid); + json_add_string(&buf, "exepath", entry->exe); + + json_end_object(&buf); + + return buf; +} + +/* handle_PROC_EVENT_PTRACE() - Handle PROC_EVENT_PTRACE events. + * + * The following are availabie for this event: + * - pid_t process_ppid + * - pid_t process_tgid + * - pid_t tracer_pid + * - pid_t tracer_tgid + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * + * Returns: + * json_t containing serialized JSON object describing this event + * + * Note: + * This appears to be called AFTER ptrace() calls, so obtaining the + * path, hash, etc of the tracer process may fail sometimes. + */ +json_t handle_PROC_EVENT_PTRACE(struct proc_event *event, agent_context_t *ctx) { + pid_t target_pid = event->event_data.ptrace.process_pid; + pid_t tracer_pid = event->event_data.ptrace.tracer_pid; + + struct proc_ledger_entry *target_entry = proc_ledger_find(ctx->proc_ledger, target_pid); + struct proc_ledger_entry *tracer_entry = proc_ledger_find(ctx->proc_ledger, tracer_pid); + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "ptrace"); + json_add_int(&buf, "pid", target_pid); + json_add_int(&buf, "tgid", event->event_data.ptrace.process_tgid); + json_add_int(&buf, "tracer_pid", tracer_pid); + json_add_int(&buf, "tracer_tgid", event->event_data.ptrace.tracer_tgid); + + if (tracer_entry && tracer_entry->exe[0]) { + json_add_string(&buf, "tracer_exepath", tracer_entry->exe); + } + + if (target_entry && target_entry->exe[0]) { + json_add_string(&buf, "target_exepath", target_entry->exe); + } + + json_end_object(&buf); + + return buf; +} + +/* handle_PROC_EVENT_SID() - Handle PROC_EVENT_SID events. + * + * The following are availabie for this event: + * - pid_t process_ppid + * - pid_t process_tgid + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * + * Returns: + * json_t containing serialized JSON object describing this event + * + * Note: + * This event occurs when the process calls setsid(). This can be + * used to detect when processes daemonize/fork/detach from a terminal. + * + * TODO: add contextual process ancestry to the output + */ +json_t handle_PROC_EVENT_SID(struct proc_event *event, agent_context_t *ctx) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.sid.process_pid); + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "sid"); + json_add_int(&buf, "pid", event->event_data.sid.process_pid); + json_add_int(&buf, "tgid", event->event_data.sid.process_tgid); + + if (entry && entry->exe[0]) { + json_add_string(&buf, "exepath", entry->exe); + } + + json_end_object(&buf); + + return buf; +} + +/* handle_PROC_EVENT_COMM() - Handle PROC_EVENT_COMM events. + * + * The following are availabie for this event: + * - pid_t process_ppid + * - pid_t process_tgid + * - char comm[16] + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * old_comm - string containing old value of comm + * + * Returns: + * json_t containing serialized JSON object describing this event + * + * Note: + * This may be triggered for prctl(PR_SET_NAME, ...) and be + * suitable for finding processes attempting to obfuscate + * themselves (ex: malware changing its name to 'sshd') + * + * Apparently this can be triggered by threads setting their names + * as well. + * + * TODO: show old comm if possible + * TODO: alert for "sketchy" names like sshd, cron, http, [kthread], ... + */ +json_t handle_PROC_EVENT_COMM(struct proc_event *event, agent_context_t *ctx, const char *old_comm) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.comm.process_pid); + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "comm"); + json_add_int(&buf, "pid", event->event_data.comm.process_pid); + json_add_int(&buf, "tgid", event->event_data.comm.process_tgid); + + json_add_string_or_null(&buf, "exepath", entry->exe); + + json_add_string_or_null(&buf, "old_comm", old_comm); + json_add_string(&buf, "new_comm", event->event_data.comm.comm); + + json_end_object(&buf); + + return buf; +} + +/* handle_PROC_EVENT_COREDUMP() - Handle PROC_EVENT_COREDUMP events. + * + * The following are availabie for this event: + * - pid_t process_ppid + * - pid_t process_tgid + * - pid_t parent_pid + * - pid_t parent_tgid + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context containing process/hash hedgers + * + * Returns: + * json_t containing serialized JSON object describing this event + */ +json_t handle_PROC_EVENT_COREDUMP(struct proc_event *event, agent_context_t *ctx) { + struct proc_ledger_entry *entry = proc_ledger_find(ctx->proc_ledger, + event->event_data.exit.process_pid); + + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "coredump"); + json_add_int(&buf, "pid", event->event_data.coredump.process_pid); + json_add_int(&buf, "tgid", event->event_data.coredump.process_tgid); + json_add_int(&buf, "parent_pid", event->event_data.coredump.parent_pid); + json_add_int(&buf, "parent_tgid", event->event_data.coredump.parent_tgid); + json_add_string(&buf, "exefile", safe_exe_path(entry)); + + json_end_object(&buf); + + return buf; +} + +/* handle_PROC_EVENT_UNKNOWN() - Handle unknown events. + * + * This is a generic placeholder for unknown/unhandled events. + * + * Args: + * event - proc_event structure (linux/cn_proc.h) + * ctx - agent context + * + * Returns: + * char * containing serialized JSON object describing the event + */ +json_t handle_PROC_EVENT_UNKNOWN(struct proc_event *event, agent_context_t *ctx) { + json_t buf = {0}; + json_init(&buf); + json_start_object(&buf); + + json_add_double(&buf, "timestamp", timestamp()); + json_add_string(&buf, "hostname", ctx->hostname); + json_add_string(&buf, "event_type", "unknown"); + json_add_int(&buf, "event_code", event->what); + + json_end_object(&buf); + + return buf; +} |
