From 99793be2abc780ad42407785707925d96af3b5bf Mon Sep 17 00:00:00 2001 From: Andi Permana Date: Mon, 24 Nov 2025 19:57:48 +0700 Subject: [PATCH 1/2] MDL-78442 tool_moodlenet: Fix directory path passed to antivirus scanner --- .../admin/tool/moodlenet/classes/local/import_backup_helper.php | 2 +- .../admin/tool/moodlenet/classes/local/import_strategy_file.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/admin/tool/moodlenet/classes/local/import_backup_helper.php b/public/admin/tool/moodlenet/classes/local/import_backup_helper.php index a2f923afb74..a53398dfb5f 100644 --- a/public/admin/tool/moodlenet/classes/local/import_backup_helper.php +++ b/public/admin/tool/moodlenet/classes/local/import_backup_helper.php @@ -86,7 +86,7 @@ class import_backup_helper { } [$filepath, $filename] = $this->remoteresource->download_to_requestdir(); - \core\antivirus\manager::scan_file($filepath, $filename, true); + \core\antivirus\manager::scan_file($filepath . DIRECTORY_SEPARATOR . $filename, $filename, true); // Check the final size of file against the user upload limits. $localsize = filesize(sprintf('%s/%s', $filepath, $filename)); diff --git a/public/admin/tool/moodlenet/classes/local/import_strategy_file.php b/public/admin/tool/moodlenet/classes/local/import_strategy_file.php index e34092a62dc..3a546401c10 100644 --- a/public/admin/tool/moodlenet/classes/local/import_strategy_file.php +++ b/public/admin/tool/moodlenet/classes/local/import_strategy_file.php @@ -78,7 +78,7 @@ class import_strategy_file implements import_strategy { // Download the file into a request directory and scan it. [$filepath, $filename] = $resource->download_to_requestdir(); - avmanager::scan_file($filepath, $filename, true); + avmanager::scan_file($filepath . DIRECTORY_SEPARATOR . $filename, $filename, true); // Check the final size of file against the user upload limits. $localsize = filesize(sprintf('%s/%s', $filepath, $filename)); From 89cbc6dc5f45417ea9f7006277f2e4c8ee7d6ae6 Mon Sep 17 00:00:00 2001 From: Andi Permana Date: Tue, 25 Nov 2025 18:21:45 +0700 Subject: [PATCH 2/2] MDL-78442 antivirus_clamav: Try SCAN first, then INSTREAM as fallback --- .../lib/antivirus/clamav/classes/scanner.php | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/public/lib/antivirus/clamav/classes/scanner.php b/public/lib/antivirus/clamav/classes/scanner.php index 72427434ec4..e6187d7e790 100644 --- a/public/lib/antivirus/clamav/classes/scanner.php +++ b/public/lib/antivirus/clamav/classes/scanner.php @@ -265,6 +265,9 @@ class scanner extends \core\antivirus\scanner { $this->set_scanning_notice($notice); return self::SCAN_RESULT_ERROR; } else { + // For Unix sockets, try SCAN first (fast), then fall back to INSTREAM if it fails. + $instreamfallback = false; + if ($type == "unixsocket") { // Execute scanning. We are running SCAN command and passing file as an argument, // it is the fastest option, but clamav user need to be able to access it, so @@ -282,9 +285,34 @@ class scanner extends \core\antivirus\scanner { // After scanning we revert permissions to initial ones. chmod($file, $perms); - } else if ($type == "tcpsocket") { - // Execute scanning by passing the entire file through the TCP socket. - // This is not fast, but is the only possibility over a network. + + // Check if SCAN failed due to permission/path issues. + if ( + strpos($output, 'File path check failure') !== false || + strpos($output, 'Permission denied') !== false + ) { + debugging('SCAN method failed, trying INSTREAM', DEBUG_DEVELOPER); + $instreamfallback = true; + fclose($socket); + // Reopen socket for INSTREAM attempt. + $socket = stream_socket_client( + $socketurl, + $errno, + $errstr, + ANTIVIRUS_CLAMAV_SOCKET_TIMEOUT + ); + if (!$socket) { + $notice = get_string('errorcantopensocket', 'antivirus_clamav', "$errstr ($errno)"); + $this->set_scanning_notice($notice); + return self::SCAN_RESULT_ERROR; + } + } + } + + if ($instreamfallback || $type == "tcpsocket") { + // Execute scanning by passing the entire file through the socket. + // This is not fast, but is the only possibility over a network and is used + // as fallback when SCAN fails. // Using 'n' as command prefix is forcing clamav to only treat \n as newline delimeter, // this is to avoid unexpected newline characters on different systems.