Skip to content

Commit 414dc95

Browse files
authored
runner: validate library_name to prevent path traversal (#9887)
Add xrt_path_or_error() to xrt_core::environment that enforces three guards before constructing a path for dlopen: 1. Reject empty strings. 2. Reject absolute paths (catches a leading '/' or Windows drive/UNC). 3. Normalize the relative path with lexically_normal() and reject any result that still contains '..', preventing traversal outside the XRT installation root. The runner's create_cpu() now calls xrt_path_or_error(libname) instead of blindly joining library_name from the recipe JSON to xilinx_xrt(). Any recipe-supplied value that escapes the XRT root throws at parse time rather than silently loading an arbitrary shared library. Signed-off-by: Soren Soe <2106410+stsoe@users.noreply.github.com>
1 parent 3bc1a20 commit 414dc95

3 files changed

Lines changed: 41 additions & 2 deletions

File tree

src/runtime_src/core/common/module_loader.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,26 @@ xilinx_xrt()
321321
return ::xilinx_xrt();
322322
}
323323

324+
sfs::path
325+
xrt_path_or_error(const std::string& file)
326+
{
327+
if (file.empty())
328+
throw std::runtime_error("Invalid empty file name");
329+
330+
std::filesystem::path path {file};
331+
332+
// No absolute path
333+
if (path.is_absolute())
334+
throw std::runtime_error("Invalid path '" + path.string() + "' cannot be absolute");
335+
336+
// May not contain any ".." to escape xilinx_xrt
337+
auto normalize = path.lexically_normal();
338+
if (normalize.string().find("..") != std::string::npos)
339+
throw std::runtime_error("Invalid path '" + normalize.string() + "' escapes xrt");
340+
341+
return xilinx_xrt() / normalize;
342+
}
343+
324344
sfs::path
325345
platform_path(const std::string& file_name)
326346
{

src/runtime_src/core/common/module_loader.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,25 @@ XRT_CORE_COMMON_EXPORT
126126
std::filesystem::path
127127
platform_path(const std::string& file_name);
128128

129+
/**
130+
* xrt_path() - Get XRT path to specified file
131+
*
132+
* @param file
133+
* Relative path to a file
134+
* Return:
135+
* Path of file rooted at xilinx_xrt() or error
136+
*
137+
* This function can be used to limit on demand loading to
138+
* files that are rooted at xilinx_xrt().
139+
*
140+
* Throws if file is an absolute path or if resulting path
141+
* escapes xilinx_xrt(). Here escape simply implies that
142+
* the resulting path contains any ".." element.
143+
*/
144+
XRT_CORE_COMMON_EXPORT
145+
std::filesystem::path
146+
xrt_path_or_error(const std::string& file);
147+
129148
/**
130149
* platform_repo_paths() - Get paths to the platform repositories
131150
*

src/runtime_src/core/common/runner/runner.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ class recipe
508508
create_cpu(const json& j)
509509
{
510510
auto name = j.at("name").get<std::string>(); // required
511-
auto library_path = xrt_core::environment::xilinx_xrt()
512-
/ j.at("library_name").get<std::string>(); // required
511+
auto libname = j.at("library_name").get<std::string>(); // required
512+
auto library_path = xrt_core::environment::xrt_path_or_error(libname);
513513
return cpu{std::move(name), library_path.string()};
514514
}
515515

0 commit comments

Comments
 (0)