Skip to content

Commit

Permalink
Merge pull request #8 from cisco-sbg/CLAM-2638-CLAM-2627-CLAM-2634-1.…
Browse files Browse the repository at this point in the history
…4.1-changes-with-CVE-fixes

Clam 2638 clam 2627 clam 2634 1.4.1 changes with CVE fixes
  • Loading branch information
micahsnyder authored Sep 3, 2024
2 parents cad552d + d898fb4 commit 0542087
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 25 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down
2 changes: 1 addition & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
32 changes: 32 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
51 changes: 40 additions & 11 deletions common/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down
6 changes: 5 additions & 1 deletion libclamav/bytecode_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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 */
Expand All @@ -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 */
};

/**
Expand Down
2 changes: 1 addition & 1 deletion libclamav/others.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
45 changes: 39 additions & 6 deletions libclamav/pdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down
5 changes: 5 additions & 0 deletions libclamav/pdfng.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 0 additions & 4 deletions unit_tests/freshclam_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,10 @@
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

Expand Down

0 comments on commit 0542087

Please sign in to comment.