util: use lstat() instead of stat() in rmdir_r to prevent symlink attacks

stat() follows symbolic links which is definitely something we don't
want. If an attacker can place a symlink inside a directory being
recursively deleted (e.g. a temporary directory), stat() will report the
type of the symlink's target rather than the symlink itself. If the
target is a directory, rmdir_r() will follow the symlink and recursively
delete the target directory's contents outside the intended directory
tree.

This has no real effect, this is only used in the test suite.

Co-Authored-by: Claude Code <noreply@anthropic.com>
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1467>
This commit is contained in:
Peter Hutterer 2026-04-16 10:27:05 +10:00 committed by Marge Bot
parent b87532dfb5
commit d97983ee5e

View file

@ -74,10 +74,12 @@ rmdir_r(const char *dir)
_autofree_ char *path = strdup_printf("%s/%s", dir, entry->d_name);
struct stat st;
if (stat(path, &st) < 0)
if (lstat(path, &st) < 0)
return -errno;
if (S_ISDIR(st.st_mode))
if (S_ISLNK(st.st_mode))
rc = unlink(path) < 0 ? -errno : 0;
else if (S_ISDIR(st.st_mode))
rc = rmdir_r(path);
else
rc = unlink(path) < 0 ? -errno : 0;