File Index
Files and directories
Sign in
FILE

audit_logread.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/net/netfilter/audit_logread.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#define _GNU_SOURCE
  4#include <errno.h>
  5#include <fcntl.h>
  6#include <poll.h>
  7#include <signal.h>
  8#include <stdint.h>
  9#include <stdio.h>
 10#include <stdlib.h>
 11#include <string.h>
 12#include <sys/socket.h>
 13#include <unistd.h>
 14#include <linux/audit.h>
 15#include <linux/netlink.h>
 16
 17static int fd;
 18
 19#define MAX_AUDIT_MESSAGE_LENGTH	8970
 20struct audit_message {
 21	struct nlmsghdr nlh;
 22	union {
 23		struct audit_status s;
 24		char data[MAX_AUDIT_MESSAGE_LENGTH];
 25	} u;
 26};
 27
 28int audit_recv(int fd, struct audit_message *rep)
 29{
 30	struct sockaddr_nl addr;
 31	socklen_t addrlen = sizeof(addr);
 32	int ret;
 33
 34	do {
 35		ret = recvfrom(fd, rep, sizeof(*rep), 0,
 36			       (struct sockaddr *)&addr, &addrlen);
 37	} while (ret < 0 && errno == EINTR);
 38
 39	if (ret < 0 ||
 40	    addrlen != sizeof(addr) ||
 41	    addr.nl_pid != 0 ||
 42	    rep->nlh.nlmsg_type == NLMSG_ERROR) /* short-cut for now */
 43		return -1;
 44
 45	return ret;
 46}
 47
 48int audit_send(int fd, uint16_t type, uint32_t key, uint32_t val)
 49{
 50	static int seq = 0;
 51	struct audit_message msg = {
 52		.nlh = {
 53			.nlmsg_len   = NLMSG_SPACE(sizeof(msg.u.s)),
 54			.nlmsg_type  = type,
 55			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
 56			.nlmsg_seq   = ++seq,
 57		},
 58		.u.s = {
 59			.mask    = key,
 60			.enabled = key == AUDIT_STATUS_ENABLED ? val : 0,
 61			.pid     = key == AUDIT_STATUS_PID ? val : 0,
 62		}
 63	};
 64	struct sockaddr_nl addr = {
 65		.nl_family = AF_NETLINK,
 66	};
 67	int ret;
 68
 69	do {
 70		ret = sendto(fd, &msg, msg.nlh.nlmsg_len, 0,
 71			     (struct sockaddr *)&addr, sizeof(addr));
 72	} while (ret < 0 && errno == EINTR);
 73
 74	if (ret != (int)msg.nlh.nlmsg_len)
 75		return -1;
 76	return 0;
 77}
 78
 79int audit_set(int fd, uint32_t key, uint32_t val)
 80{
 81	struct audit_message rep = { 0 };
 82	int ret;
 83
 84	ret = audit_send(fd, AUDIT_SET, key, val);
 85	if (ret)
 86		return ret;
 87
 88	ret = audit_recv(fd, &rep);
 89	if (ret < 0)
 90		return ret;
 91	return 0;
 92}
 93
 94int readlog(int fd)
 95{
 96	struct audit_message rep = { 0 };
 97	int ret = audit_recv(fd, &rep);
 98	const char *sep = "";
 99	char *k, *v;
100
101	if (ret < 0)
102		return ret;
103
104	if (rep.nlh.nlmsg_type != AUDIT_NETFILTER_CFG)
105		return 0;
106
107	/* skip the initial "audit(...): " part */
108	strtok(rep.u.data, " ");
109
110	while ((k = strtok(NULL, "="))) {
111		v = strtok(NULL, " ");
112
113		/* these vary and/or are uninteresting, ignore */
114		if (!strcmp(k, "pid") ||
115		    !strcmp(k, "comm") ||
116		    !strcmp(k, "subj"))
117			continue;
118
119		/* strip the varying sequence number */
120		if (!strcmp(k, "table"))
121			*strchrnul(v, ':') = '\0';
122
123		printf("%s%s=%s", sep, k, v);
124		sep = " ";
125	}
126	if (*sep) {
127		printf("\n");
128		fflush(stdout);
129	}
130	return 0;
131}
132
133void cleanup(int sig)
134{
135	audit_set(fd, AUDIT_STATUS_ENABLED, 0);
136	close(fd);
137	if (sig)
138		exit(0);
139}
140
141int main(int argc, char **argv)
142{
143	struct sigaction act = {
144		.sa_handler = cleanup,
145	};
146
147	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
148	if (fd < 0) {
149		perror("Can't open netlink socket");
150		return -1;
151	}
152
153	if (sigaction(SIGTERM, &act, NULL) < 0 ||
154	    sigaction(SIGINT, &act, NULL) < 0) {
155		perror("Can't set signal handler");
156		close(fd);
157		return -1;
158	}
159
160	audit_set(fd, AUDIT_STATUS_ENABLED, 1);
161	audit_set(fd, AUDIT_STATUS_PID, getpid());
162
163	while (1)
164		readlog(fd);
165}
~/ Read-only file preview.