static void dup_fd(int oldfd, int newfd) {
#ifdef DEBUG
- debug("%d -> %d\t\t\t[%d]\n", oldfd, newfd, getpid());
+ debug("%3d -> %3d\t\t\t[%d]\n", oldfd, newfd, getpid());
#endif
if (!initialized) {
static void close_fd(int fd) {
#ifdef DEBUG
- debug("%d -> .\t\t\t[%d]\n", fd, getpid());
+ debug("%3d -> .\t\t\t[%d]\n", fd, getpid());
#endif
if (!initialized) {
const char *, format, va_list, ap)
HOOK_FILE3(int, vfprintf, stream,
FILE *, stream, const char *, format, va_list, ap)
-/* Hardening functions (-D_FORTIFY_SOURCE=2). */
+/* Hardening functions (-D_FORTIFY_SOURCE=2), only functions from above */
HOOK_VAR_FILE2(int, __printf_chk, stdout, __vprintf_chk,
int, flag, const char *, format)
HOOK_VAR_FILE3(int, __fprintf_chk, fp, __vfprintf_chk,
va_start(ap, cmd);
result = real_fcntl(fd, cmd, va_arg(ap, void *));
va_end(ap);
+
/* We only care about duping fds. */
if (cmd == F_DUPFD && result != -1) {
int saved_errno = errno;
close_fd(fileno(fp));
return real_fclose(fp);
}
+
+
+/* Hook functions which are necessary for correct tracking. */
+
+#if defined(HAVE_VFORK) && defined(HAVE_FORK)
+pid_t vfork(void) {
+ /* vfork() is similar to fork() but the address space is shared between
+ * father and child. It's designed for fork()/exec() usage because it's
+ * faster than fork(). However according to the POSIX standard the "child"
+ * isn't allowed to perform any memory-modifications before the exec()
+ * (except the pid_t result variable of vfork()).
+ *
+ * As some programs don't adhere to the standard (e.g. the "child" closes
+ * or dups a descriptor before the exec()) and this breaks our tracking of
+ * file descriptors (e.g. it gets closed in the parent as well), we just
+ * fork() instead. This is in compliance with the POSIX standard and as
+ * most systems use copy-on-write anyway not a performance issue. */
+ return fork();
+}
+#endif