* An autrace that follows forks @ 2006-10-11 20:06 John D. Ramsdell 2006-10-11 20:24 ` Steve Grubb 2006-10-11 20:55 ` James Antill 0 siblings, 2 replies; 10+ messages in thread From: John D. Ramsdell @ 2006-10-11 20:06 UTC (permalink / raw) To: linux-audit I plan to write a version of autrace that follows forks. When run in follow forks mode, it will ptrace the child. Each time the child or one of its descendents creates a new process, the program will use the API provided by libaudit to add an audit rule for the freshly created process. If I hear of interest in this capability, I'll prepare a patch against the most recent audit source release, and share. Last summer, someone else in my company made a simple version of a fork following tracer based on the audit library; however it does not compile on my FC5 machine. The reason is he was including the kernel's headers for ptrace, which defines PTRACE_O_TRACEFORK and other symbols not part of the standard ptrace header. I don't like the idea of requiring kernel headers to compile the extended version autrace. I studied the strace source code, in particular, strace.c and process.c. I ran the preprocessor on these files using the options created on an FC5 machine, and my comments refer to the preprocessed version of these source files. When asked to follow forks, in addition to calling ptrace with the PTRACE_TRACEME option in the child, strace uses procfs to find the task ID of the process PID in the directory /proc/PID/task. Apparently, it's the only file name in the directory that parses as a positive number. Using ptrace to attach to the task ID allows strace to follow forks. I'm guessing that I have to set a ptrace option so that the parent is signaled on every descendent system call, and inspect each system call to see if a new process was created. I bet following more of the strace logic will allow me to figure out these details. I'm worried that blindly following strace's ways may lead me astray. Is there someplace I can find high-level documentation on when to use ptrace and when to use the procfs? Should I also study the GDB sources? John ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-11 20:06 An autrace that follows forks John D. Ramsdell @ 2006-10-11 20:24 ` Steve Grubb 2006-10-12 10:51 ` John D. Ramsdell 2006-10-11 20:55 ` James Antill 1 sibling, 1 reply; 10+ messages in thread From: Steve Grubb @ 2006-10-11 20:24 UTC (permalink / raw) To: linux-audit On Wednesday 11 October 2006 16:06, John D. Ramsdell wrote: > I plan to write a version of autrace that follows forks. This is a problem that requires a kernel side implementation. We've talked about it in the past and I don't think we've got code yet. We did add audit by ppid which helps a little. But we need a generic way to say that we want to audit a specific program and all its descendants. -Steve ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-11 20:24 ` Steve Grubb @ 2006-10-12 10:51 ` John D. Ramsdell 2006-10-13 14:07 ` Steve Grubb 0 siblings, 1 reply; 10+ messages in thread From: John D. Ramsdell @ 2006-10-12 10:51 UTC (permalink / raw) To: Steve Grubb; +Cc: linux-audit Steve Grubb <sgrubb@redhat.com> writes: > On Wednesday 11 October 2006 16:06, John D. Ramsdell wrote: > > I plan to write a version of autrace that follows forks. > > This is a problem that requires a kernel side implementation. Do you mean this is a problem that requires a kernel side implementation to do it well? Ptracing the descendants has the down side of changing the behavior of an application due to all the tracing signals, but until a kernel side implementation is available, the ptracing solution seems to me to be the only way to get the audit data we desire. Or do you mean the idea of using ptrace to follow forks is flawed for some reason, and will not work? One quick question, I notice autrace.c invokes /sbin/auditctl to change audit rules, but shouldn't it being using audit_add_rule and friends instead? I'll implement this change if you want me to. John ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-12 10:51 ` John D. Ramsdell @ 2006-10-13 14:07 ` Steve Grubb 2006-10-15 15:32 ` John D. Ramsdell 0 siblings, 1 reply; 10+ messages in thread From: Steve Grubb @ 2006-10-13 14:07 UTC (permalink / raw) To: John D. Ramsdell; +Cc: linux-audit On Thursday 12 October 2006 06:51, John D. Ramsdell wrote: > One quick question, I notice autrace.c invokes /sbin/auditctl to > change audit rules, but shouldn't it being using audit_add_rule and > friends instead? It was using auditctl just for expedience when the program was written. I can add the code to switch it over. -Steve ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-13 14:07 ` Steve Grubb @ 2006-10-15 15:32 ` John D. Ramsdell 0 siblings, 0 replies; 10+ messages in thread From: John D. Ramsdell @ 2006-10-15 15:32 UTC (permalink / raw) To: Steve Grubb; +Cc: linux-audit Steve Grubb <sgrubb@redhat.com> writes: > It was using auditctl just for expedience when the program was > written. I can add the code to switch it over. I wrote code that uses libaudit to add rules. After performing "yum install audit-libs-devel", I was pleased to find a manual page for audit_add_rule, but the description of the return value says to refer to audit_send. However, I found no manual page for audit_send. Studying code made me realize the error condition is <= 0, not < 0, so it's important not to guess. John static int audit_sys; /* File descriptor for socket to audit system */ static int /* Create a rule for a pid */ init_rule(struct audit_rule *r, pid_t pid) { /* Returns zero on success */ char field[PID_FIELD_SIZE]; if (snprintf(field, PID_FIELD_SIZE, "pid=%d", pid) >= PID_FIELD_SIZE) { fprintf(stderr, "Internal error in init_rule\n"); exit(1); } memset(r, 0, sizeof(*r)); if (audit_rule_syscallbyname(r, "all") < 0) { fprintf(stderr, "Illegal syscall name for audit rule for %d\n", pid); return 1; } if (audit_rule_fieldpair(r, field, AUDIT_FILTER_ENTRY)) { fprintf(stderr, "Cannot add field to audit rule for %d\n", pid); return 1; } return 0; } /* Equivalent to '/sbin/auditctl -a entry,always -F pid=%d -S all' */ static int add_rule(pid_t pid) /* Returns zero on success */ { int i; for (i = 0; i < nchildren; i++) if (pid == children[i]) /* Rule already present */ return 0; if (nchildren >= MAX_CHILDREN) { fprintf(stderr, "Too many children\n"); return 1; } struct audit_rule r[1]; if (init_rule(r, pid)) return 1; if (audit_add_rule(audit_sys, r, AUDIT_FILTER_ENTRY, AUDIT_ALWAYS) <= 0) { fprintf(stderr, "Cannot add an audit rule for %d\n", pid); return 1; } children[nchildren++] = pid; return 0; } ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-11 20:06 An autrace that follows forks John D. Ramsdell 2006-10-11 20:24 ` Steve Grubb @ 2006-10-11 20:55 ` James Antill 2006-10-12 11:09 ` John D. Ramsdell ` (2 more replies) 1 sibling, 3 replies; 10+ messages in thread From: James Antill @ 2006-10-11 20:55 UTC (permalink / raw) To: John D. Ramsdell; +Cc: linux-audit [-- Attachment #1.1: Type: text/plain, Size: 1214 bytes --] On Wed, 2006-10-11 at 16:06 -0400, John D. Ramsdell wrote: > Last summer, someone else in my company made a simple version of a > fork following tracer based on the audit library; however it does not > compile on my FC5 machine. The reason is he was including the > kernel's headers for ptrace, which defines PTRACE_O_TRACEFORK and > other symbols not part of the standard ptrace header. I don't like > the idea of requiring kernel headers to compile the extended version > autrace. Note that although the FC5 kernel-headers package might well not be updated, it's very likely that FC5 already has a kernel that supports the PTRACE_O_ options[1]. So, personally, I'd just have something like: #ifndef PTRACE_O_TRACEFORK # define PTRACE_O_TRACEFORK 0x00000002 /* from kernel-2.6.x */ #endif ...and assuming you handle the error return from PTRACE_SETOPTIONS, it should mostly just work on all relevant systems. [1] git-annotate says that flag was added on: 2005-04-16 15:20:36 -- James Antill - <james.antill@redhat.com> setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, ...); setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, ...); setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, ...); [-- Attachment #1.2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 189 bytes --] [-- Attachment #2: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-11 20:55 ` James Antill @ 2006-10-12 11:09 ` John D. Ramsdell 2006-10-12 11:40 ` John D. Ramsdell 2006-10-13 13:50 ` John D. Ramsdell 2 siblings, 0 replies; 10+ messages in thread From: John D. Ramsdell @ 2006-10-12 11:09 UTC (permalink / raw) To: James Antill; +Cc: linux-audit James Antill <james.antill@redhat.com> writes: > Note that although the FC5 kernel-headers package might well not be > updated, it's very likely that FC5 already has a kernel that supports > the PTRACE_O_ options[1]. So, personally, I'd just have something like: > > #ifndef PTRACE_O_TRACEFORK > # define PTRACE_O_TRACEFORK 0x00000002 /* from kernel-2.6.x */ > #endif Ah, and also do the same for PTRACE_EVENT_FORK and PTRACE_GETEVENTMSG. I'm guessing using these options makes it so that signals are only sent when a process is forked, not at every system call. I grep'd the kernel documentation directory but didn't find much of interest on ptrace. I haven't looked at the kernel sources yet. Googling on PTRACE_EVENT_FORK and the like keeps leading me to GDB, so I plan to look at the sources. http://www.cygwin.com/ml/gdb-patches/2003-08/msg00274.html Thanks for your help. John ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-11 20:55 ` James Antill 2006-10-12 11:09 ` John D. Ramsdell @ 2006-10-12 11:40 ` John D. Ramsdell 2006-10-13 13:50 ` John D. Ramsdell 2 siblings, 0 replies; 10+ messages in thread From: John D. Ramsdell @ 2006-10-12 11:40 UTC (permalink / raw) To: James Antill; +Cc: linux-audit James Antill <james.antill@redhat.com> writes: > So, personally, I'd just have something like: > > #ifndef PTRACE_O_TRACEFORK > # define PTRACE_O_TRACEFORK 0x00000002 /* from kernel-2.6.x */ > #endif > > ...and assuming you handle the error return from PTRACE_SETOPTIONS, it > should mostly just work on all relevant systems. The file gdb/linux_nat.c shows that GDB uses this trick, and many other useful ones. Time to cut-and-paste. John ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-11 20:55 ` James Antill 2006-10-12 11:09 ` John D. Ramsdell 2006-10-12 11:40 ` John D. Ramsdell @ 2006-10-13 13:50 ` John D. Ramsdell 2006-10-15 15:38 ` John D. Ramsdell 2 siblings, 1 reply; 10+ messages in thread From: John D. Ramsdell @ 2006-10-13 13:50 UTC (permalink / raw) To: James Antill; +Cc: linux-audit I realize others on this list aren't interested in a version of autrace that follows forks using ptrace, but I thought I'd share tricks I learned for following forks. Once the traced child is started, the parent goes into a loop waiting for signals. The tricky part seems to be that the SIGTRAP generated by the parent's immediate child has to be converted to a SIGSTOP before continuing the child. static int /* Watch all children */ watch(pid_t pid) /* This process' child is pid */ { /* Function returns an exit code */ if (add_rule(pid)) return 1; for (;;) { int status; pid = wait_for_it(&status); if (pid < 0) { if (errno == ECHILD) /* No children to wait for */ return 0; /* Declare success */ perror("wait"); return 1; } if (WIFSTOPPED(status)) { int signal = WSTOPSIG(status); if (signal == SIGTRAP) { /* Tracing causes this signal */ unsigned long msg; if (geteventmsg(pid, &msg) < 0) { perror("ptrace(PTRACE_GETEVENTMSG, ...)"); return 1; } pid_t child = (pid_t)msg; if (child) { /* The child of each traced fork is noted here */ if (add_rule(child)) return 1; } /* Only this process' child gets to this location, and just one time */ else if (setoptions(pid, PTRACE_O_TRACEFORK) < 0) { perror("ptrace(PTRACE_SETOPTIONS, ...)"); return 1; } else signal = SIGSTOP; } if (restart(pid, signal) < 0) { perror("ptrace(PTRACE_CONT, ...)"); return 1; } } } } Some of these tricks were learned from code written by someone who until recently worked at my company. There are no comments in his code describing the origin of these ideas. John ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: An autrace that follows forks 2006-10-13 13:50 ` John D. Ramsdell @ 2006-10-15 15:38 ` John D. Ramsdell 0 siblings, 0 replies; 10+ messages in thread From: John D. Ramsdell @ 2006-10-15 15:38 UTC (permalink / raw) To: linux-audit ramsdell@mitre.org (John D. Ramsdell) writes: > The tricky part seems to be that the SIGTRAP generated by the > parent's immediate child has to be converted to a SIGSTOP before > continuing the child. If you trace a shell, you find out you must always convert a SIGTRAP to a SIGSTOP. John > static int /* Watch all children */ > watch(pid_t pid) /* This process' child is pid */ > { /* Function returns an exit code */ > if (add_rule(pid)) > return 1; > for (;;) { > int status; > pid = wait_for_it(&status); > if (pid < 0) { > if (errno == ECHILD) /* No children to wait for */ > return 0; /* Declare success */ > perror("wait"); > return 1; > } > if (WIFSTOPPED(status)) { > int signal = WSTOPSIG(status); > if (signal == SIGTRAP) { /* Tracing causes this signal */ signal = SIGSTOP; > unsigned long msg; > if (geteventmsg(pid, &msg) < 0) { > perror("ptrace(PTRACE_GETEVENTMSG, ...)"); > return 1; > } > pid_t child = (pid_t)msg; > if (child) { > /* The child of each traced fork is noted here */ > if (add_rule(child)) > return 1; > } > /* Only this process' child gets to this location, and just > one time */ > else if (setoptions(pid, PTRACE_O_TRACEFORK) < 0) { > perror("ptrace(PTRACE_SETOPTIONS, ...)"); > return 1; > } /* Wrong > else > signal = SIGSTOP; */ > } > if (restart(pid, signal) < 0) { > perror("ptrace(PTRACE_CONT, ...)"); > return 1; > } > } > } > } ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2006-10-15 15:38 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-10-11 20:06 An autrace that follows forks John D. Ramsdell 2006-10-11 20:24 ` Steve Grubb 2006-10-12 10:51 ` John D. Ramsdell 2006-10-13 14:07 ` Steve Grubb 2006-10-15 15:32 ` John D. Ramsdell 2006-10-11 20:55 ` James Antill 2006-10-12 11:09 ` John D. Ramsdell 2006-10-12 11:40 ` John D. Ramsdell 2006-10-13 13:50 ` John D. Ramsdell 2006-10-15 15:38 ` John D. Ramsdell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox