From 2dfc1ac1a8a6d01d26445d39feb5e590838d3b04 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 3 Jul 2026 12:18:25 +0200 Subject: [PATCH] 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: 2ea1dac2030d ("libimcv: Support symlinks introduced by usrmerge") --- src/libimcv/pts/pts.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/libimcv/pts/pts.c b/src/libimcv/pts/pts.c index 104f88565..4c7a3e98e 100644 --- a/src/libimcv/pts/pts.c +++ b/src/libimcv/pts/pts.c @@ -327,8 +327,19 @@ METHOD(pts_t, extract_symlinks, pts_symlinks_t*, struct stat st; 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 */ - 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); if (!dir) { @@ -336,14 +347,9 @@ METHOD(pts_t, extract_symlinks, pts_symlinks_t*, strerror(errno)); return NULL; } - if (pathname.len == 1 && path[0] == '/') + if (path_len > 1 || path[0] != '/') { - path_len = 1; - } - else - { - path[pathname.len] = '/'; - path_len = pathname.len + 1; + path[path_len++] = '/'; } real_path[0] = '/'; @@ -353,7 +359,6 @@ METHOD(pts_t, extract_symlinks, pts_symlinks_t*, while (TRUE) { - entry = readdir(dir); if (!entry) {