From mboxrd@z Thu Jan 1 00:00:00 1970 From: ramsdell@mitre.org (John D. Ramsdell) Subject: autrace Date: 09 Aug 2007 10:03:20 -0400 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-audit-bounces@redhat.com Errors-To: linux-audit-bounces@redhat.com To: sgrubb@redhat.com Cc: linux-audit@redhat.com List-Id: linux-audit@redhat.com I've been successfully using the audit package to trace programs that fork by using the ptrace system call to add audit rules. As a result of tracing ever more programs, I notice I have added three features to my program that may be of use in the autrace program. To trace a program that behaves like a server, I exercise the server, and then send it a keyboard interrupt. If nothing special is done, the tracing process terminates, but not the traced processes. To handle this situation, I make the first child a process group leader with: if (setpgid(0, 0)) { /* Make child a process group leader */ perror("setpgid of child"); /* so that signals can be sent to */ return -1; /* the group */ } The tracing process stores the pid of the first child in the group variable, and then registers the following handler with SIGINT: static void signal_group(int signum) { if (group && kill(-group, signum)) perror("kill group"); if (signal(signum, SIG_DFL) == SIG_ERR) fprintf(stderr, "Setting signal %d to its default failed\n", signum); } The group variable is set to zero whenever it is known no child is running, such as when rules are being deleted. For some of the programs I trace, it is important they not be run as root. I have a -u username option, and before the first child executes the traced program, I use the following code to make use of the option's value. static int set_id(const char *username) /* Sets the group and user ID */ { /* when given a user name. */ struct passwd *pent; /* Setuid and setgid bits are */ if (!username) /* ignored on the executable file */ return 0; /* containing the program being */ else if ((pent = getpwnam(username)) == NULL) { /* traced. */ fprintf(stderr, "Cannot find user `%s'\n", username); return -1; } else if (setregid(pent->pw_gid, pent->pw_gid)) { perror("setregid"); return -1; } else if (setreuid(pent->pw_uid, pent->pw_uid)) { perror("setreuid"); return -1; } else return 0; } Finally, when printing the command to retrieve the records associated with the trace for process P, I would print ausearch -i -p P > P.txt rather than 'ausearch -i -p P' I almost always want to place the output into a file, and when I don't, it's easy to copy only part of the command. Also, the single quotes force one to be more precise with the mouse than I like to be when cutting and pasting within a terminal window. If any or all of these suggestions seem useful, I am willing to implement them in the autrace source file and send patches. On the other hand, I tried to put enough detail into this message so you can easily make the changes. John