From 6122295caf0c08c4bd85f5559958daed26ab4d3c Mon Sep 17 00:00:00 2001 From: Parag Nemade Date: Wed, 28 Feb 2024 08:17:47 +0530 Subject: [PATCH] Resolves: RHEL-31498 various flaws CVE-2024-25081 and CVE-2024-25082 Add gating.yaml file Signed-off-by: Parag Nemade --- Fix_Splinefont_shell_invocation.patch | 178 ++++++++++++++++++++++++++ fontforge.spec | 11 +- gating.yaml | 6 + 3 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 Fix_Splinefont_shell_invocation.patch create mode 100644 gating.yaml diff --git a/Fix_Splinefont_shell_invocation.patch b/Fix_Splinefont_shell_invocation.patch new file mode 100644 index 0000000..1d75f6c --- /dev/null +++ b/Fix_Splinefont_shell_invocation.patch @@ -0,0 +1,178 @@ +From a64099931ea004a08e074b08ad0984d92c25daa2 Mon Sep 17 00:00:00 2001 +From: Peter Kydas +Date: Tue, 6 Feb 2024 10:23:36 +1100 +Subject: [PATCH] fix splinefont shell command injection + +--- + fontforge/splinefont.c | 125 +++++++++++++++++++++++++++++------------ + 1 file changed, 90 insertions(+), 35 deletions(-) + +diff --git a/fontforge/splinefont.c b/fontforge/splinefont.c +index 239fdc035b..647daee109 100644 +--- a/fontforge/splinefont.c ++++ b/fontforge/splinefont.c +@@ -788,11 +788,14 @@ return( name ); + + char *Unarchive(char *name, char **_archivedir) { + char *dir = getenv("TMPDIR"); +- char *pt, *archivedir, *listfile, *listcommand, *unarchivecmd, *desiredfile; ++ char *pt, *archivedir, *listfile, *desiredfile; + char *finalfile; + int i; + int doall=false; + static int cnt=0; ++ gchar *command[5]; ++ gchar *stdoutresponse = NULL; ++ gchar *stderrresponse = NULL; + + *_archivedir = NULL; + +@@ -827,18 +830,30 @@ return( NULL ); + listfile = malloc(strlen(archivedir)+strlen("/" TOC_NAME)+1); + sprintf( listfile, "%s/" TOC_NAME, archivedir ); + +- listcommand = malloc( strlen(archivers[i].unarchive) + 1 + +- strlen( archivers[i].listargs) + 1 + +- strlen( name ) + 3 + +- strlen( listfile ) +4 ); +- sprintf( listcommand, "%s %s %s > %s", archivers[i].unarchive, +- archivers[i].listargs, name, listfile ); +- if ( system(listcommand)!=0 ) { +- free(listcommand); free(listfile); +- ArchiveCleanup(archivedir); +-return( NULL ); +- } +- free(listcommand); ++ command[0] = archivers[i].unarchive; ++ command[1] = archivers[i].listargs; ++ command[2] = name; ++ command[3] = NULL; // command args need to be NULL-terminated ++ ++ if ( g_spawn_sync( ++ NULL, ++ command, ++ NULL, ++ G_SPAWN_SEARCH_PATH, ++ NULL, ++ NULL, ++ &stdoutresponse, ++ &stderrresponse, ++ NULL, ++ NULL ++ ) == FALSE) { // did not successfully execute ++ ArchiveCleanup(archivedir); ++ return( NULL ); ++ } ++ // Write out the listfile to be read in later ++ FILE *fp = fopen(listfile, "wb"); ++ fwrite(stdoutresponse, strlen(stdoutresponse), 1, fp); ++ fclose(fp); + + desiredfile = ArchiveParseTOC(listfile, archivers[i].ars, &doall); + free(listfile); +@@ -847,22 +862,28 @@ return( NULL ); + return( NULL ); + } + +- /* I tried sending everything to stdout, but that doesn't work if the */ +- /* output is a directory file (ufo, sfdir) */ +- unarchivecmd = malloc( strlen(archivers[i].unarchive) + 1 + +- strlen( archivers[i].listargs) + 1 + +- strlen( name ) + 1 + +- strlen( desiredfile ) + 3 + +- strlen( archivedir ) + 30 ); +- sprintf( unarchivecmd, "( cd %s ; %s %s %s %s ) > /dev/null", archivedir, +- archivers[i].unarchive, +- archivers[i].extractargs, name, doall ? "" : desiredfile ); +- if ( system(unarchivecmd)!=0 ) { +- free(unarchivecmd); free(desiredfile); +- ArchiveCleanup(archivedir); +-return( NULL ); ++ command[0] = archivers[i].unarchive; ++ command[1] = archivers[i].extractargs; ++ command[2] = name; ++ command[3] = doall ? "" : desiredfile; ++ command[4] = NULL; ++ ++ if ( g_spawn_sync( ++ (gchar*)archivedir, ++ command, ++ NULL, ++ G_SPAWN_SEARCH_PATH, ++ NULL, ++ NULL, ++ &stdoutresponse, ++ &stderrresponse, ++ NULL, ++ NULL ++ ) == FALSE) { // did not successfully execute ++ free(desiredfile); ++ ArchiveCleanup(archivedir); ++ return( NULL ); + } +- free(unarchivecmd); + + finalfile = malloc( strlen(archivedir) + 1 + strlen(desiredfile) + 1); + sprintf( finalfile, "%s/%s", archivedir, desiredfile ); +@@ -885,20 +906,54 @@ struct compressors compressors[] = { + + char *Decompress(char *name, int compression) { + char *dir = getenv("TMPDIR"); +- char buf[1500]; + char *tmpfn; +- ++ gchar *command[4]; ++ gint stdout_pipe; ++ gchar buffer[4096]; ++ gssize bytes_read; ++ GByteArray *binary_data = g_byte_array_new(); ++ + if ( dir==NULL ) dir = P_tmpdir; + tmpfn = malloc(strlen(dir)+strlen(GFileNameTail(name))+2); + strcpy(tmpfn,dir); + strcat(tmpfn,"/"); + strcat(tmpfn,GFileNameTail(name)); + *strrchr(tmpfn,'.') = '\0'; +- snprintf( buf, sizeof(buf), "%s < %s > %s", compressors[compression].decomp, name, tmpfn ); +- if ( system(buf)==0 ) +-return( tmpfn ); +- free(tmpfn); +-return( NULL ); ++ ++ command[0] = compressors[compression].decomp; ++ command[1] = "-c"; ++ command[2] = name; ++ command[3] = NULL; ++ ++ // Have to use async because g_spawn_sync doesn't handle nul-bytes in the output (which happens with binary data) ++ if (g_spawn_async_with_pipes( ++ NULL, ++ command, ++ NULL, ++ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ &stdout_pipe, ++ NULL, ++ NULL) == FALSE) { ++ //command has failed ++ return( NULL ); ++ } ++ ++ // Read binary data from pipe and output to file ++ while ((bytes_read = read(stdout_pipe, buffer, sizeof(buffer))) > 0) { ++ g_byte_array_append(binary_data, (guint8 *)buffer, bytes_read); ++ } ++ close(stdout_pipe); ++ ++ FILE *fp = fopen(tmpfn, "wb"); ++ fwrite(binary_data->data, sizeof(gchar), binary_data->len, fp); ++ fclose(fp); ++ g_byte_array_free(binary_data, TRUE); ++ ++ return(tmpfn); + } + + static char *ForceFileToHaveName(FILE *file, char *exten) { diff --git a/fontforge.spec b/fontforge.spec index ce6c57e..1b7e0d9 100644 --- a/fontforge.spec +++ b/fontforge.spec @@ -2,7 +2,7 @@ Name: fontforge Version: 20230101 -Release: 10%{?dist} +Release: 11%{?dist} Summary: Outline and bitmap font editor License: GPL-3.0-or-later @@ -10,6 +10,9 @@ URL: http://fontforge.github.io/ Source0: https://github.com/fontforge/%{name}/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz # Fix translations with gettext-0.22, https://github.com/fontforge/fontforge/pull/5257 Patch0: 0001-Fix-errors-in-French-and-Italian-translations.patch +# https://github.com/fontforge/fontforge/pull/5367 +# Fixes CVE-2024-25081 and CVE-2024-25082 +Patch1: https://patch-diff.githubusercontent.com/raw/fontforge/fontforge/pull/5367.patch#/Fix_Splinefont_shell_invocation.patch Requires: xdg-utils Requires: (autotrace or potrace) @@ -70,6 +73,7 @@ This package contains documentation files for %{name}. %prep %setup -q %patch -P 0 -p1 +%patch -P 1 -p1 # Remove tests that requires Internet access sed -i '45d;82d;101d;127d' tests/CMakeLists.txt @@ -125,6 +129,11 @@ popd %doc %{_pkgdocdir} %changelog +* Tue Apr 16 2024 Parag Nemade - 20230101-11 +- Resolves: RHEL-31498 various flaws + CVE-2024-25081 and CVE-2024-25082 +- Add gating.yaml file + * Wed Jan 24 2024 Fedora Release Engineering - 20230101-10 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild diff --git a/gating.yaml b/gating.yaml new file mode 100644 index 0000000..4ca9235 --- /dev/null +++ b/gating.yaml @@ -0,0 +1,6 @@ +--- !Policy +product_versions: + - rhel-10 +decision_context: osci_compose_gate +rules: + - !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}