Merge pull request #8 from cisco-sbg/CLAM-2638-CLAM-2627-CLAM-2634-1.4.1-changes-with-CVE-fixes

Clam 2638 clam 2627 clam 2634 1.4.1 changes with CVE fixes
dev/1.4.1 clamav-1.4.1
Micah Snyder 9 months ago committed by GitHub
commit 0542087228
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      CMakeLists.txt
  2. 2
      Jenkinsfile
  3. 32
      NEWS.md
  4. 51
      common/output.c
  5. 6
      libclamav/bytecode_api.h
  6. 2
      libclamav/others.h
  7. 45
      libclamav/pdf.c
  8. 5
      libclamav/pdfng.c
  9. 4
      unit_tests/freshclam_test.py

@ -22,7 +22,7 @@ string(TIMESTAMP TODAY "%Y%m%d")
set(VERSION_SUFFIX "")
project( ClamAV
VERSION "1.4.0"
VERSION "1.4.1"
DESCRIPTION "ClamAV open source email, web, and end-point anti-virus toolkit." )
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

2
Jenkinsfile vendored

@ -10,7 +10,7 @@ properties(
parameters(
[
string(name: 'VERSION',
defaultValue: '1.4.0',
defaultValue: '1.4.1',
description: 'ClamAV version string'),
string(name: 'FRAMEWORK_BRANCH',
defaultValue: '1.4',

@ -3,6 +3,38 @@
Note: This file refers to the official packages. Things described here may
differ slightly from third-party binary packages.
## 1.4.1
ClamAV 1.4.1 is a critical patch release with the following fixes:
- [CVE-2024-20506](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-20506):
Changed the logging module to disable following symlinks on Linux and Unix
systems so as to prevent an attacker with existing access to the 'clamd' or
'freshclam' services from using a symlink to corrupt system files.
This issue affects all currently supported versions. It will be fixed in:
- 1.4.1
- 1.3.2
- 1.0.7
- 0.103.12
Thank you to Detlef for identifying this issue.
- [CVE-2024-20505](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-20505):
Fixed a possible out-of-bounds read bug in the PDF file parser that could
cause a denial-of-service (DoS) condition.
This issue affects all currently supported versions. It will be fixed in:
- 1.4.1
- 1.3.2
- 1.0.7
- 0.103.12
Thank you to OSS-Fuzz for identifying this issue.
- Removed unused Python modules from freshclam tests including deprecated
'cgi' module that is expected to cause test failures in Python 3.13.
## 1.4.0
ClamAV 1.4.0 includes the following improvements and changes:

@ -58,6 +58,12 @@
#include "output.h"
// Define O_NOFOLLOW for systems that don't have it.
// Notably, Windows doesn't have O_NOFOLLOW.
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif
#ifdef CL_THREAD_SAFE
#include <pthread.h>
pthread_mutex_t logg_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -304,7 +310,6 @@ int logg(loglevel_t loglevel, const char *str, ...)
char buffer[1025], *abuffer = NULL, *buff;
time_t currtime;
size_t len;
mode_t old_umask;
#ifdef F_WRLCK
struct flock fl;
#endif
@ -338,18 +343,36 @@ int logg(loglevel_t loglevel, const char *str, ...)
logg_open();
if (!logg_fp && logg_file) {
old_umask = umask(0037);
if ((logg_fp = fopen(logg_file, "at")) == NULL) {
umask(old_umask);
int logg_file_fd = -1;
logg_file_fd = open(logg_file, O_WRONLY | O_CREAT | O_APPEND | O_NOFOLLOW, 0640);
if (-1 == logg_file_fd) {
char errbuf[128];
cli_strerror(errno, errbuf, sizeof(errbuf));
printf("ERROR: Failed to open log file %s: %s\n", logg_file, errbuf);
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&logg_mutex);
#endif
printf("ERROR: Can't open %s in append mode (check permissions!).\n", logg_file);
if (len > sizeof(buffer))
if (abuffer)
free(abuffer);
return -1;
} else
umask(old_umask);
}
logg_fp = fdopen(logg_file_fd, "at");
if (NULL == logg_fp) {
char errbuf[128];
cli_strerror(errno, errbuf, sizeof(errbuf));
printf("ERROR: Failed to convert the open log file descriptor for %s to a FILE* handle: %s\n", logg_file, errbuf);
close(logg_file_fd);
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&logg_mutex);
#endif
if (abuffer)
free(abuffer);
return -1;
}
#ifdef F_WRLCK
if (logg_lock) {
@ -362,11 +385,16 @@ int logg(loglevel_t loglevel, const char *str, ...)
else
#endif
{
char errbuf[128];
cli_strerror(errno, errbuf, sizeof(errbuf));
printf("ERROR: Failed to lock the log file %s: %s\n", logg_file, errbuf);
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&logg_mutex);
#endif
printf("ERROR: %s is locked by another process\n", logg_file);
if (len > sizeof(buffer))
fclose(logg_fp);
logg_fp = NULL;
if (abuffer)
free(abuffer);
return -1;
}
@ -441,8 +469,9 @@ int logg(loglevel_t loglevel, const char *str, ...)
pthread_mutex_unlock(&logg_mutex);
#endif
if (len > sizeof(buffer))
if (abuffer)
free(abuffer);
return 0;
}

@ -157,6 +157,7 @@ enum FunctionalityLevels {
FUNC_LEVEL_0103_9 = 130, /**< LibClamAV release 0.103.9 */
FUNC_LEVEL_0103_10 = 131, /**< LibClamAV release 0.103.10 */
FUNC_LEVEL_0103_11 = 132, /**< LibClamAV release 0.103.11 */
FUNC_LEVEL_0103_12 = 133, /**< LibClamAV release 0.103.12 */
FUNC_LEVEL_0104 = 140, /**< LibClamAV release 0.104.0 */
FUNC_LEVEL_0104_1 = 141, /**< LibClamAV release 0.104.1 */
@ -175,6 +176,7 @@ enum FunctionalityLevels {
FUNC_LEVEL_1_0_4 = 164, /**< LibClamAV release 1.0.4 */
FUNC_LEVEL_1_0_5 = 165, /**< LibClamAV release 1.0.5 */
FUNC_LEVEL_1_0_6 = 166, /**< LibClamAV release 1.0.6 */
FUNC_LEVEL_1_0_7 = 167, /**< LibClamAV release 1.0.7 */
FUNC_LEVEL_1_1 = 180, /**< LibClamAV release 1.1.0 */
FUNC_LEVEL_1_1_1 = 181, /**< LibClamAV release 1.1.1 */
@ -188,8 +190,10 @@ enum FunctionalityLevels {
FUNC_LEVEL_1_3 = 200, /**< LibClamAV release 1.3.0 */
FUNC_LEVEL_1_3_1 = 201, /**< LibClamAV release 1.3.1 */
FUNC_LEVEL_1_3_2 = 202, /**< LibClamAV release 1.3.2 */
FUNC_LEVEL_1_4 = 210, /**< LibClamAV release 1.4.0 */
FUNC_LEVEL_1_4 = 210, /**< LibClamAV release 1.4.0 */
FUNC_LEVEL_1_4_1 = 211, /**< LibClamAV release 1.4.1 */
};
/**

@ -69,7 +69,7 @@
* in re-enabling affected modules.
*/
#define CL_FLEVEL 210
#define CL_FLEVEL 211
#define CL_FLEVEL_DCONF CL_FLEVEL
#define CL_FLEVEL_SIGTOOL CL_FLEVEL

@ -1003,8 +1003,26 @@ static size_t find_length(struct pdf_struct *pdf, struct pdf_obj *obj, const cha
return 0;
}
indirect_obj_start = pdf->map + obj->start;
bytes_remaining = pdf->size - obj->start;
if (NULL == obj->objstm) {
indirect_obj_start = (const char *)(obj->start + pdf->map);
if (!CLI_ISCONTAINED(pdf->map, pdf->size, indirect_obj_start, obj->size)) {
cli_dbgmsg("find_length: indirect object found, but not contained in PDF\n");
return 0;
}
bytes_remaining = pdf->size - obj->start;
} else {
indirect_obj_start = (const char *)(obj->start + obj->objstm->streambuf);
if (!CLI_ISCONTAINED(obj->objstm->streambuf, obj->objstm->streambuf_len, indirect_obj_start, obj->size)) {
cli_dbgmsg("find_length: indirect object found, but not contained in PDF streambuf\n");
return 0;
}
bytes_remaining = obj->objstm->streambuf_len - obj->start;
}
/* Ok so we found the indirect object, lets read the value. */
index = pdf_nextobject(indirect_obj_start, bytes_remaining);
@ -3260,15 +3278,30 @@ void pdf_handle_enc(struct pdf_struct *pdf)
obj = find_obj(pdf, pdf->objs[0], pdf->enc_objid);
if (!obj) {
cli_dbgmsg("pdf_handle_enc: can't find encrypted object %d %d\n", pdf->enc_objid >> 8, pdf->enc_objid & 0xff);
noisy_warnmsg("pdf_handle_enc: can't find encrypted object %d %d\n", pdf->enc_objid >> 8, pdf->enc_objid & 0xff);
cli_dbgmsg("pdf_handle_enc: can't find encryption object %d %d\n", pdf->enc_objid >> 8, pdf->enc_objid & 0xff);
noisy_warnmsg("pdf_handle_enc: can't find encryption object %d %d\n", pdf->enc_objid >> 8, pdf->enc_objid & 0xff);
return;
}
len = obj->size;
q = (obj->objstm) ? (const char *)(obj->start + obj->objstm->streambuf)
: (const char *)(obj->start + pdf->map);
if (NULL == obj->objstm) {
q = (const char *)(obj->start + pdf->map);
if (!CLI_ISCONTAINED(pdf->map, pdf->size, q, len)) {
cli_dbgmsg("pdf_handle_enc: encryption object found, but not contained in PDF\n");
noisy_warnmsg("pdf_handle_enc: encryption object found, but not contained in PDF\n");
return;
}
} else {
q = (const char *)(obj->start + obj->objstm->streambuf);
if (!CLI_ISCONTAINED(obj->objstm->streambuf, obj->objstm->streambuf_len, q, len)) {
cli_dbgmsg("pdf_handle_enc: encryption object found, but not contained in PDF streambuf\n");
noisy_warnmsg("pdf_handle_enc: encryption object found, but not contained in PDF streambuf\n");
return;
}
}
O = U = UE = StmF = StrF = EFF = NULL;

@ -518,6 +518,11 @@ char *pdf_parse_string(struct pdf_struct *pdf, struct pdf_obj *obj, const char *
if (!(newobj))
return NULL;
if (!CLI_ISCONTAINED(pdf->map, pdf->size, newobj->start, newobj->size)) {
cli_dbgmsg("pdf_parse_string: object not contained in PDF\n");
return NULL;
}
if (newobj == obj)
return NULL;

@ -10,14 +10,10 @@ import os
from pathlib import Path
import platform
import shutil
import subprocess
import sys
import time
import unittest
from functools import partial
from http.server import HTTPServer, BaseHTTPRequestHandler
import cgi
import testcase

Loading…
Cancel
Save