diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-11-25 11:55:36 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-11-26 08:53:45 +0000 |
| commit | 3e8de374218a6e10915300c0a1e7a6bfa274d7e7 (patch) | |
| tree | ebbe6029f3e2c372c126a4e1cb79329e51508741 /executor/files.h | |
| parent | 11dbc2540722df00e9c113b3e27c5ea707844273 (diff) | |
executor: improve glob
Don't follow symlinks when globbing.
It's haarmful for both files and dirs
(see the added comment for details).
Diffstat (limited to 'executor/files.h')
| -rw-r--r-- | executor/files.h | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/executor/files.h b/executor/files.h index 470157e84..23f06878e 100644 --- a/executor/files.h +++ b/executor/files.h @@ -6,6 +6,7 @@ #include <utility> #include <vector> +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <glob.h> @@ -16,7 +17,30 @@ static std::vector<std::string> Glob(const std::string& pattern) { glob_t buf = {}; - int res = glob(pattern.c_str(), GLOB_MARK | GLOB_NOSORT, nullptr, &buf); + buf.gl_opendir = reinterpret_cast<void* (*)(const char* name)>(opendir); + buf.gl_closedir = reinterpret_cast<void (*)(void* dirp)>(closedir); + // Use own readdir to ignore links. Links to files are not useful to us, + // we will discover the target file itself. Links to directories are harmful + // because they cause recursion, or lead outside of the target glob + // (e.g. /proc/self/{root,cwd}). + // However, we want to keep few links: /proc/self, /proc/thread-self, + // /sys/kernel/slab/kmalloc-64 (may be a link with slab merging). + // This is a hacky way to do it b/c e.g. "self" will be matched in all paths, + // not just /proc. A proper fix would require writing completly custom version of glob + // that would support recursion and would allow using/not using links on demand. + buf.gl_readdir = [](void* dir) -> dirent* { + for (;;) { + struct dirent* ent = readdir(static_cast<DIR*>(dir)); + if (!ent || ent->d_type != DT_LNK || + !strcmp(ent->d_name, "self") || + !strcmp(ent->d_name, "thread-self") || + !strcmp(ent->d_name, "kmalloc-64")) + return ent; + } + }, + buf.gl_stat = stat; + buf.gl_lstat = lstat; + int res = glob(pattern.c_str(), GLOB_MARK | GLOB_NOSORT | GLOB_ALTDIRFUNC, nullptr, &buf); if (res != 0 && res != GLOB_NOMATCH) failmsg("glob failed", "pattern='%s' res=%d", pattern.c_str(), res); std::vector<std::string> files; |
