已合并
fix: harden path validation in reselect_static_kernel_with_path #40497
rich创建于 7月8日
fix: harden path validation in reselect_static_kernel_with_path #40497
已合并
rich创建于 7月8日
4 个文件变更+40-24
Mtest/_inductor/test_npu_static_kernel.py+24-11
@@ -1,13 +1,10 @@
1-import os
2-import subprocess
3-import datetime
4-from pathlib import Path
5import stat1import stat
2+import unittest
3+from pathlib import Path
4+ 
6import torch_npu5import torch_npu
7-from torch_npu._inductor.config import log6+from torch_npu._inductor.npu_static_kernel import StaticKernelCompiler, safe_resolve_output_dir
8-from torch_npu._inductor.npu_static_kernel import StaticKernelCompiler
9from torch_npu.testing.testcase import TestCase, run_tests7from torch_npu.testing.testcase import TestCase, run_tests
10-from torch_npu._inductor.npu_static_kernel import safe_resolve_output_dir
11 8 
12 9 
13class TestNpuStaticKernel(TestCase):10class TestNpuStaticKernel(TestCase):
@@ -63,9 +60,9 @@ class TestNpuStaticKernel(TestCase):
63 safe_resolve_output_dir(build_path)60 safe_resolve_output_dir(build_path)
64 61 
65 def test_uninstall_static_kernel_no_path(self):62 def test_uninstall_static_kernel_no_path(self):
66- from torch_npu._inductor.npu_static_kernel import _uninstall_path, uninstall_static_kernel63+ from torch_npu._inductor.npu_static_kernel import uninstall_static_kernel
67- _uninstall_path = None64+ with unittest.mock.patch("torch_npu._inductor.npu_static_kernel._uninstall_path", None):
68- uninstall_static_kernel()65+ uninstall_static_kernel()
69 66 
70 def test_static_kernel_compiler_context_manager(self):67 def test_static_kernel_compiler_context_manager(self):
71 with StaticKernelCompiler() as compiler:68 with StaticKernelCompiler() as compiler:
@@ -80,7 +77,6 @@ class TestNpuStaticKernel(TestCase):
80 77 
81 def test_safe_resolve_output_dir_absolute_path(self):78 def test_safe_resolve_output_dir_absolute_path(self):
82 import tempfile79 import tempfile
83- import shutil
84 with tempfile.TemporaryDirectory() as tmpdir:80 with tempfile.TemporaryDirectory() as tmpdir:
85 abs_dir = Path(tmpdir) / "test_build"81 abs_dir = Path(tmpdir) / "test_build"
86 abs_dir.mkdir()82 abs_dir.mkdir()
@@ -88,6 +84,23 @@ class TestNpuStaticKernel(TestCase):
88 self.assertTrue(result.exists())84 self.assertTrue(result.exists())
89 self.assertIn("kernel_aot_optimization_build_outputs", str(result))85 self.assertIn("kernel_aot_optimization_build_outputs", str(result))
90 86 
87+ def test_reselect_static_kernel_with_path_not_string(self):
88+ with self.assertRaisesRegex(RuntimeError, "path must be a string"):
89+ torch_npu._C._aclnn_reselect_static_kernel_with_path(123)
90+ 
91+ def test_reselect_static_kernel_with_path_null_byte(self):
92+ with self.assertRaisesRegex(RuntimeError, "null byte"):
93+ torch_npu._C._aclnn_reselect_static_kernel_with_path("test\x00dir")
94+ 
95+ def test_reselect_static_kernel_with_path_non_existent(self):
96+ with self.assertRaisesRegex(RuntimeError, "failed to resolve path"):
97+ torch_npu._C._aclnn_reselect_static_kernel_with_path("/nonexistent/path")
98+ 
99+ def test_reselect_static_kernel_with_path_is_file(self):
100+ import tempfile
101+ with tempfile.NamedTemporaryFile() as f:
102+ with self.assertRaisesRegex(RuntimeError, "must be a directory"):
103+ torch_npu._C._aclnn_reselect_static_kernel_with_path(f.name)
91 104 
92if __name__ == "__main__":105if __name__ == "__main__":
93 run_tests()106 run_tests()
Mtorch_npu/csrc/core/npu/interface/OpInterface.cpp+3-3
@@ -47,10 +47,10 @@ aclnnStatus ReselectStaticKernelWithPath(const std::string &path)
47 if (aclnnReselectStaticKernelWithPathFunc == nullptr) {47 if (aclnnReselectStaticKernelWithPathFunc == nullptr) {
48 aclnnReselectStaticKernelWithPathFunc =48 aclnnReselectStaticKernelWithPathFunc =
49 (AclnnApiFunc)TORCH_NPU_GET_FUNC(aclnnReselectStaticKernelWithPath);49 (AclnnApiFunc)TORCH_NPU_GET_FUNC(aclnnReselectStaticKernelWithPath);
50+ TORCH_CHECK(aclnnReselectStaticKernelWithPathFunc,
51+ "Failed to find function ", "aclnnReselectStaticKernelWithPath",
52+ PTA_ERROR(ErrCode::NOT_FOUND));
50 }53 }
51- TORCH_CHECK(aclnnReselectStaticKernelWithPathFunc,
52- "Failed to find function ", "aclnnReselectStaticKernelWithPath",
53- PTA_ERROR(ErrCode::NOT_FOUND));
54 auto ret = aclnnReselectStaticKernelWithPathFunc(path.c_str());54 auto ret = aclnnReselectStaticKernelWithPathFunc(path.c_str());
55 return ret;55 return ret;
56}56}
Mtorch_npu/csrc/core/npu/interface/OpInterface.h+1-2
@@ -18,8 +18,7 @@ bool IsExistAclnnSilentCheck();
18aclnnStatus ReselectStaticKernel();18aclnnStatus ReselectStaticKernel();
19 19 
20/**20/**
21- This Api is used to reselect static kernel with a specified path,21+ This Api is used to reselect static kernel with a specified path.
22- it need to be called once at process.
23 */22 */
24aclnnStatus ReselectStaticKernelWithPath(const std::string &path);23aclnnStatus ReselectStaticKernelWithPath(const std::string &path);
25 24 
Mtorch_npu/csrc/npu/Module.cpp+12-8
@@ -1,5 +1,7 @@
1#include <chrono>1#include <chrono>
2+#include <cstdlib>
2#include <future>3#include <future>
4+#include <linux/limits.h>
3#include <sstream>5#include <sstream>
4#include <sys/stat.h>6#include <sys/stat.h>
5#include <thread>7#include <thread>
@@ -2093,13 +2095,15 @@ PyObject* THNPModule_aclnn_reselect_static_kernel_with_path(
2093 TORCH_CHECK(path.find('\0') == std::string::npos,2095 TORCH_CHECK(path.find('\0') == std::string::npos,
2094 "path must not contain null byte",2096 "path must not contain null byte",
2095 PTA_ERROR(ErrCode::PARAM));2097 PTA_ERROR(ErrCode::PARAM));
2096- struct stat st;2098+ char abs_path[PATH_MAX] = {'\0'};
2097- TORCH_CHECK(stat(path.c_str(), &st) == 0,2099+ TORCH_CHECK(realpath(path.c_str(), abs_path) != nullptr,
2098- "path does not exist: ", path,2100+ "failed to resolve path: ", path,
2099 PTA_ERROR(ErrCode::NOT_FOUND));2101 PTA_ERROR(ErrCode::NOT_FOUND));
2100- TORCH_CHECK(S_ISDIR(st.st_mode),2102+ struct stat st;
2101- "path must be a directory: ", path,2103+ TORCH_CHECK(stat(abs_path, &st) == 0 && S_ISDIR(st.st_mode),
2104+ "path must be a directory: ", abs_path,
2102 PTA_ERROR(ErrCode::PARAM));2105 PTA_ERROR(ErrCode::PARAM));
2106+ std::string resolved_path(abs_path);
2103 2107 
2104 NPUStatus ret = c10_npu::emptyAllNPUStream();2108 NPUStatus ret = c10_npu::emptyAllNPUStream();
2105 TORCH_CHECK(2109 TORCH_CHECK(
@@ -2111,8 +2115,8 @@ PyObject* THNPModule_aclnn_reselect_static_kernel_with_path(
2111 static const auto task_queue_enable =2115 static const auto task_queue_enable =
2112 c10_npu::option::OptionsManager::GetTaskQueueEnable();2116 c10_npu::option::OptionsManager::GetTaskQueueEnable();
2113 if (task_queue_enable == 2) {2117 if (task_queue_enable == 2) {
2114- auto acl_call = [path]() -> int {2118+ auto acl_call = [resolved_path]() -> int {
2115- return c10_npu::opapi::ReselectStaticKernelWithPath(path);2119+ return c10_npu::opapi::ReselectStaticKernelWithPath(resolved_path);
2116 };2120 };
2117 at_npu::native::OpCommand::RunOpApiV2("reselect_static_kernel_with_path", acl_call);2121 at_npu::native::OpCommand::RunOpApiV2("reselect_static_kernel_with_path", acl_call);
2118 NPUStatus ret = c10_npu::emptyAllNPUStream();2122 NPUStatus ret = c10_npu::emptyAllNPUStream();
@@ -2122,7 +2126,7 @@ PyObject* THNPModule_aclnn_reselect_static_kernel_with_path(
2122 ret,2126 ret,
2123 PTA_ERROR(ErrCode::INTERNAL));2127 PTA_ERROR(ErrCode::INTERNAL));
2124 } else {2128 } else {
2125- NPU_CHECK_ERROR(c10_npu::opapi::ReselectStaticKernelWithPath(path));2129+ NPU_CHECK_ERROR(c10_npu::opapi::ReselectStaticKernelWithPath(resolved_path));
2126 }2130 }
2127 2131 
2128 Py_RETURN_NONE;2132 Py_RETURN_NONE;