123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- /*
- This file is licensed under the GPL v2 (http://www.gnu.org/licenses/gpl2.txt) (some parts was originally borrowed from proc events example)
- https://stackoverflow.com/questions/6075013/detect-launching-of-programs-on-linux-platform/8255487#8255487
- */
- #if defined(__aarch64__)
- int main() {}
- #else
- #define _XOPEN_SOURCE 700
- #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 volatile bool need_exit = false;
- /*
- * 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 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;
- }
- 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:
- printf("exec: tid=%d pid=%d\n",
- nlcn_msg.proc_ev.event_data.exec.process_pid,
- nlcn_msg.proc_ev.event_data.exec.process_tgid);
- 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;
- }
- }
- return 0;
- }
- static void on_sigint(__attribute__ ((unused)) int unused)
- {
- need_exit = true;
- }
- int main()
- {
- 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);
- }
- #endif
|