commit:     56905522dfd178685b6225c6be89560cb02c445c
Author:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Mon Jun 20 00:37:04 2016 +0000
Commit:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Mon Jun 20 00:37:04 2016 +0000
URL:        https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=56905522

pspax: rewrite core loop to use *at funcs

This makes the code a bit simpler & robust.

 pspax.c | 228 ++++++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 128 insertions(+), 100 deletions(-)

diff --git a/pspax.c b/pspax.c
index c64472c..67b7678 100644
--- a/pspax.c
+++ b/pspax.c
@@ -40,20 +40,47 @@ static pid_t show_pid = 0;
 static uid_t show_uid = (uid_t)-1;
 static gid_t show_gid = (gid_t)-1;
 
-static FILE *proc_fopen(pid_t pid, const char *file)
+static int proc_open(int pfd, const char *file)
 {
-       char path[__PAX_UTILS_PATH_MAX];
-       snprintf(path, sizeof(path), PROC_DIR "/%u/%s", pid, file);
-       path[sizeof(path) - 1] = '\0';
-       return fopen(path, "r");
+       return openat(pfd, file, O_RDONLY|O_CLOEXEC);
 }
 
-static char *get_proc_name_cmdline(pid_t pid)
+static FILE *proc_fopen(int pfd, const char *file)
+{
+       int fd;
+       FILE *fp;
+
+       fd = proc_open(pfd, file);
+       if (fd == -1)
+               return NULL;
+
+       fp = fdopen(fd, "re");
+       if (fp == NULL)
+               close(fd);
+
+       return fp;
+}
+
+static elfobj *proc_readelf(int pfd)
+{
+       int fd;
+       elfobj *elf;
+
+       fd = proc_open(pfd, "exe");
+       if (fd == -1)
+               return NULL;
+
+       elf = readelf_fd("proc/exe", fd, 0);
+       close(fd);
+       return elf;
+}
+
+static char *get_proc_name_cmdline(int pfd)
 {
        FILE *fp;
        static char str[1024];
 
-       fp = proc_fopen(pid, "cmdline");
+       fp = proc_fopen(pfd, "cmdline");
        if (fp == NULL)
                return NULL;
 
@@ -64,15 +91,15 @@ static char *get_proc_name_cmdline(pid_t pid)
        return (str);
 }
 
-static char *get_proc_name(pid_t pid)
+static char *get_proc_name(int pfd)
 {
        FILE *fp;
        static char str[BUFSIZ];
 
        if (wide_output)
-               return get_proc_name_cmdline(pid);
+               return get_proc_name_cmdline(pfd);
 
-       fp = proc_fopen(pid, "stat");
+       fp = proc_fopen(pfd, "stat");
        if (fp == NULL)
                return NULL;
 
@@ -90,12 +117,12 @@ static char *get_proc_name(pid_t pid)
        return (str+1);
 }
 
-static int get_proc_maps(pid_t pid)
+static int get_proc_maps(int pfd)
 {
        FILE *fp;
        static char str[BUFSIZ];
 
-       if ((fp = proc_fopen(pid, "maps")) == NULL)
+       if ((fp = proc_fopen(pfd, "maps")) == NULL)
                return -1;
 
        while (fgets(str, sizeof(str), fp)) {
@@ -126,12 +153,12 @@ static int get_proc_maps(pid_t pid)
        return 0;
 }
 
-static int print_executable_mappings(pid_t pid)
+static int print_executable_mappings(int pfd)
 {
        FILE *fp;
        static char str[BUFSIZ];
 
-       if ((fp = proc_fopen(pid, "maps")) == NULL)
+       if ((fp = proc_fopen(pfd, "maps")) == NULL)
                return -1;
 
        while (fgets(str, sizeof(str), fp)) {
@@ -169,28 +196,24 @@ static int print_executable_mappings(pid_t pid)
 # define NOTE_TO_SELF
 #endif
 
-static struct passwd *get_proc_passwd(pid_t pid)
+static struct passwd *get_proc_passwd(int pfd)
 {
        struct stat st;
-       struct passwd *pwd;
-       char path[__PAX_UTILS_PATH_MAX];
-
-       snprintf(path, sizeof(path), PROC_DIR "/%u/stat", pid);
+       struct passwd *pwd = NULL;
 
-       if (stat(path, &st) != -1)
-               if ((pwd = getpwuid(st.st_uid)) != NULL)
-                       return pwd;
+       if (fstatat(pfd, "stat", &st, AT_SYMLINK_NOFOLLOW) != -1)
+               pwd = getpwuid(st.st_uid);
 
-       return NULL;
+       return pwd;
 }
 
-static char *get_proc_status(pid_t pid, const char *name)
+static char *get_proc_status(int pfd, const char *name)
 {
        FILE *fp;
        size_t len;
        static char str[BUFSIZ];
 
-       if ((fp = proc_fopen(pid, "status")) == NULL)
+       if ((fp = proc_fopen(pfd, "status")) == NULL)
                return NULL;
 
        len = strlen(name);
@@ -208,13 +231,13 @@ static char *get_proc_status(pid_t pid, const char *name)
        return NULL;
 }
 
-static char *get_pid_attr(pid_t pid)
+static char *get_pid_attr(int pfd)
 {
        FILE *fp;
        char *p;
        static char buf[BUFSIZ];
 
-       if ((fp = proc_fopen(pid, "attr/current")) == NULL)
+       if ((fp = proc_fopen(pfd, "attr/current")) == NULL)
                return NULL;
 
        if (fgets(buf, sizeof(buf), fp) != NULL)
@@ -225,13 +248,13 @@ static char *get_pid_attr(pid_t pid)
        return buf;
 }
 
-static char *get_pid_addr(pid_t pid)
+static char *get_pid_addr(int pfd)
 {
        FILE *fp;
        char *p;
        static char buf[BUFSIZ];
 
-       if ((fp = proc_fopen(pid, "ipaddr")) == NULL)
+       if ((fp = proc_fopen(pfd, "ipaddr")) == NULL)
                return NULL;
 
        if (fgets(buf, sizeof(buf), fp) != NULL)
@@ -242,15 +265,15 @@ static char *get_pid_addr(pid_t pid)
        return buf;
 }
 
-static const char *get_proc_type(pid_t pid)
+static const char *get_proc_type(int pfd)
 {
-       char fname[32];
        elfobj *elf;
        const char *ret;
 
-       snprintf(fname, sizeof(fname), PROC_DIR "/%u/exe", pid);
-       if ((elf = readelf(fname)) == NULL)
+       elf = proc_readelf(pfd);
+       if (elf == NULL)
                return NULL;
+
        ret = get_elfetype(elf);
        unreadelf(elf);
        return ret;
@@ -290,15 +313,15 @@ static char *scanelf_file_phdr(elfobj *elf)
        return ret;
 }
 /* we scan the elf file two times when the -e flag is given. But we don't need 
-e very often so big deal */
-static const char *get_proc_phdr(pid_t pid)
+static const char *get_proc_phdr(int pfd)
 {
-       char fname[32];
        elfobj *elf;
        const char *ret;
 
-       snprintf(fname, sizeof(fname), PROC_DIR "/%u/exe", pid);
-       if ((elf = readelf(fname)) == NULL)
+       elf = proc_readelf(pfd);
+       if (elf == NULL)
                return NULL;
+
        ret = scanelf_file_phdr(elf);
        unreadelf(elf);
        return ret;
@@ -312,9 +335,9 @@ static void pspax(const char *find_name)
        pid_t ppid = show_pid;
        int have_attr, have_addr, wx;
        struct passwd *pwd;
-       struct stat st;
        const char *pax, *type, *name, *attr, *addr;
        char *caps;
+       int pfd;
        WRAP_SYSCAP(ssize_t length; cap_t cap_d;)
 
        WRAP_SYSCAP(cap_d = cap_init());
@@ -339,76 +362,81 @@ static void pspax(const char *find_name)
                        have_addr ? "IPADDR" : "", show_phdr ? "STACK LOAD" : 
"");
 
        while ((de = readdir(dir))) {
-               errno = 0;
-               stat(de->d_name, &st);
-               if ((errno != ENOENT) && (errno != EACCES)) {
-                       pid = (pid_t) atoi((char *) basename((char *) 
de->d_name));
-                       if (find_name && pid) {
-                               char *str = get_proc_name(pid);
-                               if (!str)
-                                       continue;
-                               if (strcmp(str, find_name) != 0)
-                                       pid = 0;
-                       }
-                       if (((ppid > 0) && (pid != ppid)) || !pid)
-                               continue;
+               /* Check the name first if it's an int as it's faster. */
+               pid = atoi(de->d_name);
+               if (pid == 0)
+                       continue;
 
-                       wx = get_proc_maps(pid);
+               /* Get an open handle so the kernel won't reap on us later. */
+               pfd = open(de->d_name, O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY);
+               if (pfd == -1)
+                       continue;
 
-                       if (noexec != writeexec) {
-                               if ((wx == 1) && (writeexec != wx))
-                                       goto next_pid;
+               if (find_name && pid) {
+                       char *str = get_proc_name(pfd);
+                       if (!str)
+                               goto next_pid;
+                       if (strcmp(str, find_name) != 0)
+                               pid = 0;
+               }
+               if (ppid > 0 && pid != ppid)
+                       goto next_pid;
 
-                               if ((wx == 0) && writeexec)
-                                       goto next_pid;
-                       }
+               wx = get_proc_maps(pfd);
 
-                       pwd  = get_proc_passwd(pid);
-                       pax  = get_proc_status(pid, "PAX");
-                       type = get_proc_type(pid);
-                       name = get_proc_name(pid);
-                       attr = (have_attr ? get_pid_attr(pid) : NULL);
-                       addr = (have_addr ? get_pid_addr(pid) : NULL);
-
-                       if (pwd) {
-                               if (show_uid != (uid_t)-1)
-                                       if (pwd->pw_uid != show_uid)
-                                               continue;
-
-                               if (show_gid != (gid_t)-1)
-                                       if (pwd->pw_gid != show_gid)
-                                               continue;
-                       }
+               if (noexec != writeexec) {
+                       if (wx == 1 && writeexec != wx)
+                               goto next_pid;
 
-                       /* this is a non-POSIX function */
-                       caps = NULL;
-                       WRAP_SYSCAP(capgetp(pid, cap_d));
-                       WRAP_SYSCAP(caps = cap_to_text(cap_d, &length));
-
-                       if (pwd && strlen(pwd->pw_name) >= 8)
-                               pwd->pw_name[8] = 0;
-
-                       if (show_all || type) {
-                               printf("%-8s %-6d %-6s %-4s %-10s %-16s %-4s %s 
%s %s\n",
-                                      pwd  ? pwd->pw_name : "--------",
-                                      pid,
-                                      pax  ? pax  : "---",
-                                      (wx == 1) ? "w|x" : (wx == -1) ? "---" : 
"w^x",
-                                      type ? type : "-------",
-                                      name ? name : "-----",
-                                      caps ? caps : " = ",
-                                      attr ? attr : "",
-                                      addr ? addr : "",
-                                      show_phdr ? get_proc_phdr(pid) : "");
-                               if (verbose && wx)
-                                       print_executable_mappings(pid);
-                       }
+                       if (wx == 0 && writeexec)
+                               goto next_pid;
+               }
 
-                       WRAP_SYSCAP(if (caps) cap_free(caps));
+               pwd  = get_proc_passwd(pfd);
+               pax  = get_proc_status(pfd, "PAX");
+               type = get_proc_type(pfd);
+               name = get_proc_name(pfd);
+               attr = (have_attr ? get_pid_attr(pfd) : NULL);
+               addr = (have_addr ? get_pid_addr(pfd) : NULL);
 
-               next_pid:
-                       continue;
+               if (pwd) {
+                       if (show_uid != (uid_t)-1)
+                               if (pwd->pw_uid != show_uid)
+                                       goto next_pid;
+
+                       if (show_gid != (gid_t)-1)
+                               if (pwd->pw_gid != show_gid)
+                                       goto next_pid;
+               }
+
+               /* this is a non-POSIX function */
+               caps = NULL;
+               WRAP_SYSCAP(capgetp(pfd, cap_d));
+               WRAP_SYSCAP(caps = cap_to_text(cap_d, &length));
+
+               if (pwd && strlen(pwd->pw_name) >= 8)
+                       pwd->pw_name[8] = 0;
+
+               if (show_all || type) {
+                       printf("%-8s %-6d %-6s %-4s %-10s %-16s %-4s %s %s 
%s\n",
+                              pwd  ? pwd->pw_name : "--------",
+                              pid,
+                              pax  ? pax  : "---",
+                              (wx == 1) ? "w|x" : (wx == -1) ? "---" : "w^x",
+                              type ? type : "-------",
+                              name ? name : "-----",
+                              caps ? caps : " = ",
+                              attr ? attr : "",
+                              addr ? addr : "",
+                              show_phdr ? get_proc_phdr(pfd) : "");
+                       if (verbose && wx)
+                               print_executable_mappings(pfd);
                }
+
+               WRAP_SYSCAP(if (caps) cap_free(caps));
+
+ next_pid:
+               close(pfd);
        }
        closedir(dir);
 }

Reply via email to