diff options
author | Alexey Izbyshev <izbyshev@ispras.ru> | 2023-03-10 17:00:50 +0300 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2023-04-11 09:18:01 -0400 |
commit | 35e9831156efc1b54e1a91917ba0f787d5df3353 (patch) | |
tree | 796775814a33d02b596cdc9f09a4fe1508f16e8f /src | |
parent | 7c41047285a24a97e700b4fb5b6b69f4505e2d82 (diff) | |
download | musl-35e9831156efc1b54e1a91917ba0f787d5df3353.tar.gz musl-35e9831156efc1b54e1a91917ba0f787d5df3353.tar.bz2 musl-35e9831156efc1b54e1a91917ba0f787d5df3353.tar.xz musl-35e9831156efc1b54e1a91917ba0f787d5df3353.zip |
nftw: fix use of uninitialized struct stat
If lstat/stat fails with EACCES, st is left uninitialized, but its
st_dev/st_ino fields are then used in several places:
* for FTW_MOUNT check (in practice typically results in a false
positive and an early return)
* for copying to the new struct history (though the struct is not used
afterwards since we don't recurse in this case)
* for cycle detection check (could theoretically result in a false
positive and an early return)
To avoid adding FTW_NS checks to all these places, fix this by
zero-initializing st_dev/st_ino (which can never match an existing
dentry due to zero inode being reserved in Linux), and check for FTW_NS
only when handling FTW_MOUNT since we need two valid dentries there.
Diffstat (limited to 'src')
-rw-r--r-- | src/misc/nftw.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/src/misc/nftw.c b/src/misc/nftw.c index fcd25a73..71bc62ee 100644 --- a/src/misc/nftw.c +++ b/src/misc/nftw.c @@ -31,6 +31,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, int err; struct FTW lev; + st.st_dev = st.st_ino = 0; + if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) { if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st)) type = FTW_SLN; @@ -46,7 +48,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, type = FTW_F; } - if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev) + if ((flags & FTW_MOUNT) && h && type != FTW_NS && st.st_dev != h->dev) return 0; new.chain = h; |