From 9f763f84b1eb6132b40f351f9cb16511f361ede0 Mon Sep 17 00:00:00 2001 From: LI Qing Date: Thu, 21 Oct 2021 11:47:03 +0800 Subject: [PATCH] Add the check of pathname in rename syscall --- deps/sefs | 2 +- src/libos/src/fs/file_ops/rename.rs | 8 ++++++++ test/rename/main.c | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/deps/sefs b/deps/sefs index ca5dabb6..5fd86adb 160000 --- a/deps/sefs +++ b/deps/sefs @@ -1 +1 @@ -Subproject commit ca5dabb6ef3d4e9fdd704c40b85098cee8b63c5f +Subproject commit 5fd86adbfa0b173d10d5afebd871a237bf25f688 diff --git a/src/libos/src/fs/file_ops/rename.rs b/src/libos/src/fs/file_ops/rename.rs index 4812583b..595f99b7 100644 --- a/src/libos/src/fs/file_ops/rename.rs +++ b/src/libos/src/fs/file_ops/rename.rs @@ -8,6 +8,14 @@ pub fn do_renameat(old_fs_path: &FsPath, new_fs_path: &FsPath) -> Result<()> { let oldpath = old_fs_path.to_abs_path()?; let newpath = new_fs_path.to_abs_path()?; + + let old_path = Path::new(&oldpath); + let new_path = Path::new(&newpath); + // Limitation: only compare the whole path components, cannot handle symlink or ".." + if new_path.starts_with(old_path) && new_path != old_path { + return_errno!(EINVAL, "newpath contains a path prefix of the oldpath"); + } + let current = current!(); let fs = current.fs().read().unwrap(); diff --git a/test/rename/main.c b/test/rename/main.c index deae3f91..ed380b50 100644 --- a/test/rename/main.c +++ b/test/rename/main.c @@ -178,6 +178,31 @@ static int test_rename_dir() { return 0; } +static int test_rename_dir_to_subdir() { + const char *old_dir = "/root/test_old_dir"; + mode_t mode = 00775; + int ret; + + char sub_dir[PATH_MAX] = { 0 }; + ret = snprintf(sub_dir, sizeof(sub_dir), "%s/test_new_dir", old_dir); + if (ret >= sizeof(sub_dir) || ret < 0) { + THROW_ERROR("failed to init new dir path"); + } + + if (mkdir(old_dir, mode) < 0) { + THROW_ERROR("failed to mkdir"); + } + + ret = rename(old_dir, sub_dir); + if (ret == 0 || errno != EINVAL) { + THROW_ERROR("failed to check rename dir to subdir"); + } + if (rmdir(old_dir) < 0) { + THROW_ERROR("failed to rmdir"); + } + return 0; +} + // ============================================================================ // Test suite main // ============================================================================ @@ -188,6 +213,7 @@ static test_case_t test_cases[] = { TEST_CASE(test_rename_with_target_exist), TEST_CASE(test_renameat), TEST_CASE(test_rename_dir), + TEST_CASE(test_rename_dir_to_subdir), }; int main(int argc, const char *argv[]) {