From 4060a0e9dad36565ae4f082d748d6a46234e8423 Mon Sep 17 00:00:00 2001 From: datenwolf <@datenwolf.net> Date: Tue, 18 Jan 2022 00:32:24 +0100 Subject: initial commit --- pmon.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 pmon.c (limited to 'pmon.c') diff --git a/pmon.c b/pmon.c new file mode 100644 index 0000000..b7a5efa --- /dev/null +++ b/pmon.c @@ -0,0 +1,201 @@ +// code taken from https://bewareofgeek.livejournal.com/2945.html +// and extended with pid_cmdline and using it to print the cmdline on exec + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char* pid_cmdline(pid_t const pid) +{ + char path[] = "/proc/xxxxxxxxxxx/cmdline"; + snprintf(path, sizeof(path)-1, "/proc/%lu/cmdline", (long unsigned)pid); + FILE *fil = fopen(path, "r"); + if( !fil ){ return NULL; } + size_t cmdlen = 0; + char *cmdline = NULL; + getline(&cmdline, &cmdlen, fil); + fclose(fil); + return cmdline; +} + +/* + * connect to netlink + * returns netlink socket, or -1 on error + */ +static int nl_connect() +{ + int rc; + int nl_sock; + struct sockaddr_nl sa_nl; + + nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + if (nl_sock == -1) { + perror("socket"); + return -1; + } + + sa_nl.nl_family = AF_NETLINK; + sa_nl.nl_groups = CN_IDX_PROC; + sa_nl.nl_pid = getpid(); + + rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); + if (rc == -1) { + perror("bind"); + close(nl_sock); + return -1; + } + + return nl_sock; +} + +/* + * subscribe on proc events (process notifications) + */ +static int set_proc_ev_listen(int nl_sock, bool enable) +{ + int rc; + struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) { + struct cn_msg cn_msg; + enum proc_cn_mcast_op cn_mcast; + }; + } nlcn_msg; + + memset(&nlcn_msg, 0, sizeof(nlcn_msg)); + nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg); + nlcn_msg.nl_hdr.nlmsg_pid = getpid(); + nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE; + + nlcn_msg.cn_msg.id.idx = CN_IDX_PROC; + nlcn_msg.cn_msg.id.val = CN_VAL_PROC; + nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op); + + nlcn_msg.cn_mcast = enable ? PROC_CN_MCAST_LISTEN : PROC_CN_MCAST_IGNORE; + + rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); + if (rc == -1) { + perror("netlink send"); + return -1; + } + + return 0; +} + +/* + * handle a single process event + */ +static volatile bool need_exit = false; +static int handle_proc_ev(int nl_sock) +{ + int rc; + struct __attribute__ ((aligned(NLMSG_ALIGNTO))) { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) { + struct cn_msg cn_msg; + struct proc_event proc_ev; + }; + } nlcn_msg; + + while (!need_exit) { + rc = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); + if (rc == 0) { + /* shutdown? */ + return 0; + } else if (rc == -1) { + if (errno == EINTR) continue; + perror("netlink recv"); + return -1; + } + char* cmdline = NULL; + switch (nlcn_msg.proc_ev.what) { + case PROC_EVENT_NONE: + printf("set mcast listen ok\n"); + break; + case PROC_EVENT_FORK: + printf("fork: parent tid=%d pid=%d -> child tid=%d pid=%d\n", + nlcn_msg.proc_ev.event_data.fork.parent_pid, + nlcn_msg.proc_ev.event_data.fork.parent_tgid, + nlcn_msg.proc_ev.event_data.fork.child_pid, + nlcn_msg.proc_ev.event_data.fork.child_tgid); + break; + case PROC_EVENT_EXEC: + cmdline = pid_cmdline(nlcn_msg.proc_ev.event_data.exec.process_pid); + printf("exec: tid=%d pid=%d, cmd='%s'\n", + nlcn_msg.proc_ev.event_data.exec.process_pid, + nlcn_msg.proc_ev.event_data.exec.process_tgid, + cmdline ); + break; + case PROC_EVENT_UID: + printf("uid change: tid=%d pid=%d from %d to %d\n", + nlcn_msg.proc_ev.event_data.id.process_pid, + nlcn_msg.proc_ev.event_data.id.process_tgid, + nlcn_msg.proc_ev.event_data.id.r.ruid, + nlcn_msg.proc_ev.event_data.id.e.euid); + break; + case PROC_EVENT_GID: + printf("gid change: tid=%d pid=%d from %d to %d\n", + nlcn_msg.proc_ev.event_data.id.process_pid, + nlcn_msg.proc_ev.event_data.id.process_tgid, + nlcn_msg.proc_ev.event_data.id.r.rgid, + nlcn_msg.proc_ev.event_data.id.e.egid); + break; + case PROC_EVENT_EXIT: + printf("exit: tid=%d pid=%d exit_code=%d\n", + nlcn_msg.proc_ev.event_data.exit.process_pid, + nlcn_msg.proc_ev.event_data.exit.process_tgid, + nlcn_msg.proc_ev.event_data.exit.exit_code); + break; + default: + printf("unhandled proc event\n"); + break; + } + if( cmdline ){ free(cmdline); } + } + + return 0; +} + +static void on_sigint(int unused) +{ + need_exit = true; +} + +int main(int argc, const char *argv[]) +{ + int nl_sock; + int rc = EXIT_SUCCESS; + + signal(SIGINT, &on_sigint); + siginterrupt(SIGINT, true); + + nl_sock = nl_connect(); + if (nl_sock == -1) + exit(EXIT_FAILURE); + + rc = set_proc_ev_listen(nl_sock, true); + if (rc == -1) { + rc = EXIT_FAILURE; + goto out; + } + + rc = handle_proc_ev(nl_sock); + if (rc == -1) { + rc = EXIT_FAILURE; + goto out; + } + + set_proc_ev_listen(nl_sock, false); + +out: + close(nl_sock); + exit(rc); +} -- cgit v1.2.3