From 7ff44f4b90a718195d4521b3caa48eeeb7699fbf Mon Sep 17 00:00:00 2001 From: "Chris West (Faux)" Date: Thu, 8 Feb 2018 10:40:08 +0000 Subject: extrace: use openat() for speedup This reduces the timeframe where the inherently racy access to /proc is done, and removes some unnecessary snprintf. Closes: #2 [via git-merge-pr] --- extrace.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/extrace.c b/extrace.c index 30a8c43..25d16ac 100644 --- a/extrace.c +++ b/extrace.c @@ -106,6 +106,13 @@ struct { char cmdline[CMDLINE_DB_MAX]; } pid_db[PID_DB_SIZE]; +static int +open_proc_dir(pid_t pid) { + char name[48]; + snprintf(name, sizeof name, "/proc/%d", pid); + return open(name, O_DIRECTORY); +} + static int pid_depth(pid_t pid) { @@ -231,14 +238,14 @@ print_shquoted(const char *s) } static void -print_env(pid_t pid) +print_env(int proc_dir_fd) { - char name[PATH_MAX]; + int fd; FILE *env; fprintf(output, " "); - snprintf(name, sizeof name, "/proc/%d/environ", pid); - if ((env = fopen(name, "r"))) { + fd = openat(proc_dir_fd, "environ", O_RDONLY); + if (fd >= 0 && (env = fdopen(fd, "r"))) { char *line = 0, *eq = 0; size_t linelen = 0; while (getdelim(&line, &linelen, '\0', env) >= 0) { @@ -264,7 +271,7 @@ print_env(pid_t pid) static void handle_msg(struct cn_msg *cn_hdr) { - char cmdline[CMDLINE_MAX], name[PATH_MAX]; + char cmdline[CMDLINE_MAX]; char exe[PATH_MAX]; char cwd[PATH_MAX]; char *argvrest; @@ -275,10 +282,17 @@ handle_msg(struct cn_msg *cn_hdr) if (ev->what == PROC_EVENT_EXEC) { pid_t pid = ev->event_data.exec.process_pid; int i = 0; + int proc_dir_fd = open_proc_dir(pid); + if (proc_dir_fd < 0) { + /* TODO: warn we dropped something? */ + return; + } d = pid_depth(pid); - if (d < 0) + if (d < 0) { + close(proc_dir_fd); return; + } if (show_exit || !flat) { for (i = 0; i < PID_DB_SIZE - 1; i++) @@ -293,11 +307,9 @@ handle_msg(struct cn_msg *cn_hdr) pid_db[i].start = ev->timestamp_ns; } - snprintf(name, sizeof name, "/proc/%d/cmdline", pid); - memset(&cmdline, 0, sizeof cmdline); - fd = open(name, O_RDONLY); - if (fd > 0) { + fd = openat(proc_dir_fd, "cmdline", O_RDONLY); + if (fd >= 0) { r = read(fd, cmdline, sizeof cmdline); close(fd); @@ -305,8 +317,7 @@ handle_msg(struct cn_msg *cn_hdr) cmdline[r] = 0; if (full_path) { - snprintf(name, sizeof name, "/proc/%d/exe", pid); - r2 = readlink(name, exe, sizeof exe); + r2 = readlinkat(proc_dir_fd, "exe", exe, sizeof exe); if (r2 > 0) exe[r2] = 0; } @@ -315,8 +326,7 @@ handle_msg(struct cn_msg *cn_hdr) } if (show_cwd) { - snprintf(name, sizeof name, "/proc/%d/cwd", pid); - r3 = readlink(name, cwd, sizeof cwd); + r3 = readlinkat(proc_dir_fd, "cwd", cwd, sizeof cwd); if (r3 > 0) cwd[r3] = 0; } @@ -351,9 +361,10 @@ handle_msg(struct cn_msg *cn_hdr) if (r == sizeof cmdline) fprintf(output, "... "); - if (show_env) { - print_env(pid); - } + if (show_env) + print_env(proc_dir_fd); + + close(proc_dir_fd); fprintf(output, "\n"); fflush(output); -- cgit 1.4.1