Windows: 1.4.5 reintroduces RAM disk scan failure fixed in 0.103.1 (regression of 478fe1b3)
Summary
ClamAV 1.4.5 reintroduces a bug that was deliberately fixed in 0.103.1 by
478fe1b3 ("Allow scans even if realpath lookup fails").
On Windows, clamd again refuses to scan any file on a volume whose path cannot be
resolved by GetFinalPathNameByHandleW(..., VOLUME_NAME_DOS). It replies
<path>: File path check failure: <strerror>. ERROR and the file is never scanned. ImDisk
RAM disks are the same trigger named in the 0.103.1 fix: the volume can have a drive letter
yet not be registered with the Windows Mount Manager, so it has no resolvable DOS name.
2b7eb60f9 ("Harden quarantine actions against TOCTOU races") made the resolution failure
fatal again, in the same files 478fe1b3 had changed.
Related: #196 ("ClamAV fails to scan file on RAM Disks") reports the underlying resolution failure and has been open since 2021. This report is about the change in consequence: the warning used to be cosmetic and the scan proceeded; since 1.4.5 the scan does not happen.
Environment (reproduced on a clean install)
- ClamAV 1.4.5 and 1.4.6 — both fail. 1.4.4 works.
- Windows Server 2019
- RAM disk (ImDisk) mounted as
E:, volume labelRAMDisk clamddriven with a single-file scan command over the local socket- No quarantine action configured
Steps to reproduce
- Create a RAM disk with a drive letter (e.g.
E:) using a driver that does not register the volume with the Mount Manager. ImDisk reproduces this. - Place a file on it, e.g.
E:\test\eicar.com. - Submit that path to
clamdfor scanning.
Observed
Daemon log:
WARNING: File path check failure for: E:\test\...Client reply:
E:\test\...: File path check failure: Unknown error. ERROREvery scan fails, and fails fast (~12 ms). The same file on C: scans normally on the same
machine and the same build. Moving the scanned tree off the RAM disk resolves it entirely.
The failure is permanent for that volume, not a transient race — 128 of 128 scans fail.
Expected
The file is scanned and the result reported, as in 1.4.4 and earlier.
Root cause
clamd/scanner.c:225 (1.4.5) made cli_realpath() failure fatal:
ret = cli_realpath(scan_path, &scan_filename);
if (CL_SUCCESS != ret) {
conn_reply_errno(scandata->conn, filename, "File path check failure:");
logg(LOGG_WARNING, "File path check failure for: %s\n", filename);
scandata->errors++;
free(filename);
return (CL_EMEM == ret) ? ret : CL_SUCCESS; /* file is never scanned */
}Before 2b7eb60f9 this site logged the warning and then scanned the file anyway. The
warning text is not new — it appears benignly in 1.4.2 logs on the same kind of volume,
each occurrence followed by a normal OK result.
On Windows cli_realpath() (libclamav/others_common.c) resolves via
cli_get_filepath_from_handle(), which returns CL_EOPEN when
GetFinalPathNameByHandleW(hFile, NULL, 0, VOLUME_NAME_DOS) returns 0. VOLUME_NAME_DOS
depends on a Mount Manager DOS-name mapping, so it fails for volumes that lack one — even
though the file itself opened successfully a moment earlier through the same drive letter.
Previously fixed in 0.103.1
478fe1b3 (Micah Snyder, 2020-12-14) made this exact failure non-fatal, for this exact
driver:
The security improvement to perform file realpath lookups prior to a scan has the adverse effect of causing file scans to fail on Windows when scanning on some filesystems.
Specifically, it was observed that the ImDisk driver doesn't handle the
IRP_MJ_QUERY_INFORMATIONmessage so the call to look up the realpath usingGetFinalPathNameByHandleW()doesn't work.[...] this patch simply allows the scan to proceed if the realpath lookup failed. If the user is using the quarantine (remove/move) features AND if the scan target filepath has a directory junction (soft link), then the quarantine action will fail. It's not ideal but it is quite unlikely.
The 0.103.1 NEWS entry records the same decision. 478fe1b3 touched clamd/scanner.c,
clamdscan/proto.c, clamscan/manager.c and libclamav/others_common.c — the same four
files 2b7eb60f9 changed.
That commit also evaluated resolving via the NT device path (\Device\ImDisk0\...) and
rejected mapping it back to R:\ as relying on a default-drive-letter assumption, so I have
not proposed that route here.
Affected versions
| Branch | Affected | Not affected |
|---|---|---|
| 1.4.x | 1.4.5, 1.4.6 | 1.4.0 – 1.4.4 |
| 1.5.x | 1.5.3, 1.5.4 | 1.5.0 – 1.5.2 |
main |
yes (3826779c) |
— |
| 1.3.x and earlier | no — never backported | all |
1.4.5 / 1.4.6 confirmed by testing; 1.5.x and main by code inspection — the same change
landed as ed99acde on rel/1.5 and 3826779c on main. The 1.4.6 / 1.5.4 follow-ups
(Preserve resolved quarantine source paths, Support safe quarantine removal on FreeBSD)
address FreeBSD F_KINFO hard-link resolution and do not touch this path.
Because 1.4.5 and 1.4.6 are security releases, staying on 1.4.4 to keep scanning working means forgoing eleven CVE fixes. There is currently no release with both the TOCTOU fix and working scan coverage on these volumes.
Suggested fix
Restore the 478fe1b3 behavior: on cli_realpath() failure, log the warning and scan the
submitted path rather than skipping the file.
If the 2020 trade-off is no longer acceptable, it can be narrowed rather than reverted — scan
the submitted path but suppress virusaction() for that file. VirusEvent is the only
consumer in clamd that acts on the path, and clamd does not appear to use the quarantine
actions in common/actions.c at all (action_source_* and actions.h do not appear under
clamd/). On Windows nothing is given up either way, since virusaction() is a stub there
(clamd/clamd_others.c:92).
Happy to test a patch on a reproducing setup.
Source: Cisco-Talos/clamav