pts: Fix potential crash when resolving symlinks

When the passed path was longer than the local buffer, while still
passing the `opendir()` call (e.g. `/\0` followed by padding), the access
via original chunk length to write a final `/` wrote outside of the
buffer.  The same could happen later when adding directory names because
`path_len` was based on that same length.

Fixes: 2ea1dac203 ("libimcv: Support symlinks introduced by usrmerge")
This commit is contained in:
Tobias Brunner
2026-07-24 08:47:37 +02:00
parent fdf12edd85
commit 2dfc1ac1a8
+14 -9
View File
@@ -327,8 +327,19 @@ METHOD(pts_t, extract_symlinks, pts_symlinks_t*,
struct stat st; struct stat st;
DIR *dir; DIR *dir;
path_len = strnlen(pathname.ptr, pathname.len);
if (!path_len)
{
DBG1(DBG_PTS, "empty directory path");
return NULL;
}
if (path_len >= sizeof(path)-1)
{
DBG1(DBG_PTS, "directory path is too long");
return NULL;
}
/* open directory and prepare pathnames */ /* open directory and prepare pathnames */
snprintf(path, BUF_LEN-1, "%.*s", (int)pathname.len, pathname.ptr); snprintf(path, BUF_LEN-1, "%.*s", (int)path_len, pathname.ptr);
dir = opendir(path); dir = opendir(path);
if (!dir) if (!dir)
{ {
@@ -336,14 +347,9 @@ METHOD(pts_t, extract_symlinks, pts_symlinks_t*,
strerror(errno)); strerror(errno));
return NULL; return NULL;
} }
if (pathname.len == 1 && path[0] == '/') if (path_len > 1 || path[0] != '/')
{ {
path_len = 1; path[path_len++] = '/';
}
else
{
path[pathname.len] = '/';
path_len = pathname.len + 1;
} }
real_path[0] = '/'; real_path[0] = '/';
@@ -353,7 +359,6 @@ METHOD(pts_t, extract_symlinks, pts_symlinks_t*,
while (TRUE) while (TRUE)
{ {
entry = readdir(dir); entry = readdir(dir);
if (!entry) if (!entry)
{ {