Introduce filename__readable to check readability by opening
the file directly. Since the access(R_OK) just checks the
readability based on real UID/GID, it is ignored that the
effective UID/GID and capabilities for some special file (e.g.
/proc/kcore).
filename__readable() directly opens given file with O_RDONLY
so that the kernel checks it by effective UID/GID and capabilities.
---
 tools/perf/util/symbol.c |   32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 54c4ff2..a469346 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1641,6 +1641,20 @@ static int find_matching_kcore(struct map *map, char 
*dir, size_t dir_sz)
        return ret;
 }
 
+/*
+ * Use open(O_RDONLY) to check readability directly instead of access(R_OK)
+ * since access(R_OK) only checks with real UID/GID but open() use effective
+ * UID/GID and actual capabilities (e.g. /proc/kcore requires CAP_SYS_RAWIO).
+ */
+static bool filename__readable(const char *file)
+{
+       int fd = open(file, O_RDONLY);
+       if (fd < 0)
+               return false;
+       close(fd);
+       return true;
+}
+
 static char *dso__find_kallsyms(struct dso *dso, struct map *map)
 {
        u8 host_build_id[BUILD_ID_SIZE];
@@ -1668,7 +1682,6 @@ static char *dso__find_kallsyms(struct dso *dso, struct 
map *map)
        /* Use /proc/kallsyms if possible */
        if (is_host) {
                DIR *d;
-               int fd;
 
                /* If no cached kcore go with /proc/kallsyms */
                d = opendir(path);
@@ -1677,16 +1690,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct 
map *map)
                closedir(d);
 
                /*
-                * Do not check the build-id cache, until we know we cannot use
-                * /proc/kcore.
+                * Do not check the build-id cache, unless we know we cannot use
+                * /proc/kcore or module maps don't match to /proc/kallsyms.
+                * To check readability of /proc/kcore, do not use access(R_OK)
+                * since /proc/kcore requires CAP_SYS_RAWIO to read and access
+                * can't check it.
                 */
-               fd = open("/proc/kcore", O_RDONLY);
-               if (fd != -1) {
-                       close(fd);
-                       /* If module maps match go with /proc/kallsyms */
-                       if (!validate_kcore_addresses("/proc/kallsyms", map))
-                               goto proc_kallsyms;
-               }
+               if (filename__readable("/proc/kcore") &&
+                   !validate_kcore_addresses("/proc/kallsyms", map))
+                       goto proc_kallsyms;
 
                /* Find kallsyms in build-id cache with kcore */
                if (!find_matching_kcore(map, path, sizeof(path)))

Reply via email to