summaryrefslogtreecommitdiff
path: root/pmon.c
diff options
context:
space:
mode:
authordatenwolf <@datenwolf.net>2022-01-18 00:32:24 +0100
committerdatenwolf <@datenwolf.net>2022-01-18 00:32:24 +0100
commit4060a0e9dad36565ae4f082d748d6a46234e8423 (patch)
treef70542f519814ddae23491fb680371cd04c237bf /pmon.c
downloadpmon-4060a0e9dad36565ae4f082d748d6a46234e8423.tar.gz
pmon-4060a0e9dad36565ae4f082d748d6a46234e8423.tar.bz2
initial commit
Diffstat (limited to 'pmon.c')
-rw-r--r--pmon.c201
1 files changed, 201 insertions, 0 deletions
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 <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/connector.h>
+#include <linux/cn_proc.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+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);
+}