2 * Copyright 2005-09,2011,2015 Red Hat Inc., Durham, North Carolina.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Steve Grubb <sgrubb@redhat.com>
32 #include <linux/net.h>
37 * This program will add the audit rules to trace a process similar
38 * to strace. It will then execute the process.
40 static int threat = 0;
41 static int count_rules(void);
42 static int count_em(int fd);
43 extern int delete_all_rules(int fd);
45 static void usage(void)
47 fprintf(stderr, "usage: autrace [-r] program\n");
50 static int insert_rule(int audit_fd, const char *field)
53 int flags = AUDIT_FILTER_EXIT;
54 int action = AUDIT_ALWAYS;
55 struct audit_rule_data *rule = malloc(sizeof(struct audit_rule_data));
56 int machine = audit_detect_machine();
61 memset(rule, 0, sizeof(struct audit_rule_data));
64 if (machine != MACH_AARCH64) {
65 rc |= audit_rule_syscallbyname_data(rule, "open");
66 rc |= audit_rule_syscallbyname_data(rule, "creat");
67 rc |= audit_rule_syscallbyname_data(rule, "rename");
68 rc |= audit_rule_syscallbyname_data(rule, "unlink");
69 rc |= audit_rule_syscallbyname_data(rule, "mknod");
70 rc |= audit_rule_syscallbyname_data(rule, "mkdir");
71 rc |= audit_rule_syscallbyname_data(rule, "rmdir");
72 rc |= audit_rule_syscallbyname_data(rule, "chown");
73 rc |= audit_rule_syscallbyname_data(rule, "lchown");
74 rc |= audit_rule_syscallbyname_data(rule, "chmod");
75 rc |= audit_rule_syscallbyname_data(rule, "link");
76 rc |= audit_rule_syscallbyname_data(rule, "symlink");
77 rc |= audit_rule_syscallbyname_data(rule, "readlink");
79 rc |= audit_rule_syscallbyname_data(rule, "openat");
80 rc |= audit_rule_syscallbyname_data(rule, "truncate");
81 rc |= audit_rule_syscallbyname_data(rule, "renameat");
82 rc |= audit_rule_syscallbyname_data(rule, "unlinkat");
83 rc |= audit_rule_syscallbyname_data(rule, "mknodat");
84 rc |= audit_rule_syscallbyname_data(rule, "mkdirat");
85 rc |= audit_rule_syscallbyname_data(rule, "chdir");
86 rc |= audit_rule_syscallbyname_data(rule, "fchownat");
87 rc |= audit_rule_syscallbyname_data(rule, "fchmodat");
88 rc |= audit_rule_syscallbyname_data(rule, "linkat");
89 rc |= audit_rule_syscallbyname_data(rule, "symlinkat");
90 rc |= audit_rule_syscallbyname_data(rule, "readlinkat");
91 rc |= audit_rule_syscallbyname_data(rule, "execve");
92 rc |= audit_rule_syscallbyname_data(rule, "name_to_handle_at");
94 if (machine != MACH_X86 && machine != MACH_S390X &&
95 machine != MACH_S390) {
96 rc |= audit_rule_syscallbyname_data(rule, "connect");
97 rc |= audit_rule_syscallbyname_data(rule, "bind");
98 rc |= audit_rule_syscallbyname_data(rule, "accept");
99 rc |= audit_rule_syscallbyname_data(rule, "sendto");
100 rc |= audit_rule_syscallbyname_data(rule, "recvfrom");
101 rc |= audit_rule_syscallbyname_data(rule, "accept4");
104 rc |= audit_rule_syscallbyname_data(rule, "sendfile");
106 rc = audit_rule_syscallbyname_data(rule, "all");
109 t_field = strdup(field);
110 rc = audit_rule_fieldpair_data(&rule, t_field, flags);
114 rc = audit_add_rule_data(audit_fd, rule, flags, action);
118 // Now if i386, lets add its network rules
119 if (machine == MACH_X86 || machine == MACH_S390X ||
120 machine == MACH_S390) {
121 int i, a0[6] = { SYS_CONNECT, SYS_BIND, SYS_ACCEPT, SYS_SENDTO,
122 SYS_RECVFROM, SYS_ACCEPT4 };
123 for (i=0; i<6; i++) {
126 memset(rule, 0, sizeof(struct audit_rule_data));
127 rc |= audit_rule_syscallbyname_data(rule, "socketcall");
128 snprintf(pair, sizeof(pair), "a0=%d", a0[i]);
129 rc |= audit_rule_fieldpair_data(&rule, pair, flags);
130 t_field = strdup(field);
131 rc |= audit_rule_fieldpair_data(&rule, t_field, flags);
133 rc |= audit_add_rule_data(audit_fd, rule, flags, action);
139 fprintf(stderr, "Error inserting audit rule for %s\n", field);
144 int key_match(struct audit_reply *rep)
151 * check that user is root
152 * check to see if program exists
153 * if so fork, child waits for parent
154 * parent clears audit rules, loads audit all syscalls with child's pid
155 * parent tells child to go & waits for sigchld
156 * child exec's program
157 * parent deletes rules after getting sigchld
159 int main(int argc, char *argv[])
169 if (strcmp(argv[cmd], "-h") == 0) {
173 if (strcmp(argv[cmd], "-r") == 0) {
178 fprintf(stderr, "You must be root to run this program.\n");
181 if (access(argv[cmd], X_OK)) {
183 fprintf(stderr, "Error - can't find: %s\n", argv[cmd]);
185 fprintf(stderr, "Error checking %s (%s)\n",
186 argv[cmd], strerror(errno));
189 set_aumessage_mode(MSG_STDERR, DBG_NO);
190 switch (count_rules())
193 if (errno == ECONNREFUSED)
195 "The audit system is disabled\n");
198 "Error - can't get rule count.\n");
204 "autrace cannot be run with rules loaded.\n"
205 "Please delete all rules using 'auditctl -D' if you "
206 "really wanted to\nrun this command.\n");
210 fprintf(stderr, "Error creating pipe.\n");
214 switch ((pid=fork()))
217 fprintf(stderr, "Error forking.\n");
221 printf("Waiting to execute: %s\n", argv[cmd]);
222 while (read(fd[0], buf, 1) == -1 && errno == EINTR)
225 execvp(argv[cmd], &argv[cmd]);
226 fprintf(stderr, "Failed to exec %s\n", argv[cmd]);
228 default: /* Parent */
230 fcntl(fd[1], F_SETFD, FD_CLOEXEC);
234 audit_fd = audit_open();
237 snprintf(field, sizeof(field), "pid=%d", pid);
238 if (insert_rule(audit_fd, field)) {
240 (void)delete_all_rules(audit_fd);
243 snprintf(field, sizeof(field), "ppid=%d", pid);
244 if (insert_rule(audit_fd, field)) {
246 (void)delete_all_rules(audit_fd);
250 if (write(fd[1],"1", 1) != 1) {
252 (void)delete_all_rules(audit_fd);
255 waitpid(pid, NULL, 0);
257 puts("Cleaning up...");
258 (void)delete_all_rules(audit_fd);
261 printf("Trace complete. "
262 "You can locate the records with "
263 "\'ausearch -i -p %d\'\n",
271 static int count_rules(void)
279 rc = audit_request_rules_list_data(fd);
281 total = count_em(fd);
289 static int count_em(int fd)
291 int i, retval, count = 0;
292 int timeout = 40; /* loop has delay of .1 - this is 4 seconds */
293 struct audit_reply rep;
297 FD_SET(fd, &read_mask);
299 for (i = 0; i < timeout; i++) {
300 retval = audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);
304 if (rep.type == NLMSG_ERROR &&
305 rep.error->error == 0)
308 t.tv_usec = 100000; /* .1 second */
310 retval=select(fd+1, &read_mask, NULL, NULL, &t);
311 } while (retval < 0 && errno == EINTR);
316 case AUDIT_LIST_RULES: