autrace

John D. Ramsdell ramsdell at mitre.org
Thu Aug 9 14:03:20 UTC 2007


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




More information about the Linux-audit mailing list