RHBZ#1999409: VirtIO-FS: fix parent and forbid absolute target path in SetReparsePoint
Previously, parent node-id for FUSE_SYMLINK was set to target's parent,
which is wrong. Set parent to linkname's parent.
Also, allow relative target paths only to prevent paths outside of
VirtIO-FS from being target paths.
@@ -2267,11 +2267,15 @@ static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
int linkname_len, targetname_len;
uint64_t parent;
- UNREFERENCED_PARAMETER(FileContext);
UNREFERENCED_PARAMETER(Size);
DBG("\"%S\"", FileName);
+ if (!(ReparseData->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
Cleanup(FileSystem, FileContext, FileName, FspCleanupDelete);
CopyMemory(TargetName,
@@ -2293,20 +2297,20 @@ static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
}
SCOPE_EXIT(targetname, { FspPosixDeletePath(targetname); });
- Status = PathWalkthough(VirtFs, targetname, &filename, &parent);
+ Status = FspPosixMapWindowsToPosixPath(FileName + 1, &linkname);
if (!NT_SUCCESS(Status))
{
return Status;
}
+ SCOPE_EXIT(linkname, { FspPosixDeletePath(linkname); });
- Status = FspPosixMapWindowsToPosixPath(FileName + 1, &linkname);
+ Status = PathWalkthough(VirtFs, linkname, &filename, &parent);
if (!NT_SUCCESS(Status))
{
return Status;
}
- SCOPE_EXIT(linkname, { FspPosixDeletePath(linkname); });
- linkname_len = lstrlenA(linkname) + 1;
+ linkname_len = lstrlenA(filename) + 1;
targetname_len = lstrlenA(targetname) + 1;
symlink_in = (FUSE_SYMLINK_IN *)HeapAlloc(GetProcessHeap(),
@@ -2320,7 +2324,7 @@ static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
FUSE_HEADER_INIT(&symlink_in->hdr, FUSE_SYMLINK, parent,
linkname_len + targetname_len);
- CopyMemory(symlink_in->names, linkname, linkname_len);
+ CopyMemory(symlink_in->names, filename, linkname_len);
CopyMemory(symlink_in->names + linkname_len, targetname, targetname_len);
Status = VirtFsFuseRequest(VirtFs->Device, symlink_in,
