From 8c3e8ad3955ae29cdd0540496f56536dce2f65bc Mon Sep 17 00:00:00 2001 From: Zdenek Dohnal Date: Thu, 13 Jun 2024 14:10:46 +0200 Subject: [PATCH] RHEL-38837 CVE-2024-33871 ghostscript: OPVP device arbitrary code execution via custom Driver library Resolves: RHEL-38837 --- ghostscript.spec | 15 +++- gs-cve-2024-33871.patch | 154 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 gs-cve-2024-33871.patch diff --git a/ghostscript.spec b/ghostscript.spec index 8ec48a0..5d1ae4d 100644 --- a/ghostscript.spec +++ b/ghostscript.spec @@ -37,7 +37,7 @@ Name: ghostscript Summary: Interpreter for PostScript language & PDF Version: 9.27 -Release: 12%{?dist} +Release: 13%{?dist} License: AGPLv3+ @@ -113,6 +113,16 @@ Patch020: ghostscript-9.27-CVE-2023-28879.patch Patch021: ghostscript-9.27-CVE-2023-38559.patch Patch022: ghostscript-9.27-CVE-2023-4042.patch Patch023: ghostscript-9.27-avoid-divide-by-zero-in-devices.patch +# RHEL-38837 CVE-2024-33871 ghostscript: OPVP device arbitrary code execution via custom Driver library +# the patch is based on upstream code from 9.50, where a new -dSAFER implementation was introduced and +# -dSAFER was made default for any gs calls. To do not backport the whole new -dSAFER implementation, +# to do not collide with any future backports related with -dSAFER and to do not change the current default +# for ghostscript in RHEL 8, only part of the new -dSAFER implementation was backported, +# and the several functions, variables and macros prefix was changed to 'opvp' and used only +# for OPVP device, which results in changing the default only for this device and fixing the CVE. +# Downside of the fix is if someone depends on unsafe settings of driver for OPVP device +# (via Postscript code in command -c, via Postscript code in input file), gs will start to fail. +Patch024: gs-cve-2024-33871.patch # Downstream patches -- these should be always included when doing rebase: @@ -453,6 +463,9 @@ done # ============================================================================= %changelog +* Wed Jun 12 2024 Zdenek Dohnal - 9.27-13 +- CVE-2024-33871 ghostscript: OPVP device arbitrary code execution via custom Driver library + * Tue Sep 19 2023 Richard Lescak - 9.27-12 - fix to prevent divison by zero in devices - Resolves: rhbz#2235009 diff --git a/gs-cve-2024-33871.patch b/gs-cve-2024-33871.patch new file mode 100644 index 0000000..596eb0d --- /dev/null +++ b/gs-cve-2024-33871.patch @@ -0,0 +1,154 @@ +diff --git a/Resource/Init/gs_init.ps b/Resource/Init/gs_init.ps +index 55a785e..be77534 100644 +--- a/Resource/Init/gs_init.ps ++++ b/Resource/Init/gs_init.ps +@@ -2607,4 +2607,6 @@ WRITESYSTEMDICT { + % be 'true' in some cases. + userdict /AGM_preserve_spots //false put + ++.opvpactivatepathcontrol ++ + % The interpreter will run the initial procedure (start). +diff --git a/base/gslibctx.c b/base/gslibctx.c +index 1ed6093..14fb57c 100644 +--- a/base/gslibctx.c ++++ b/base/gslibctx.c +@@ -435,3 +435,27 @@ gs_check_file_permission (gs_memory_t *mem, const char *fname, const int len, co + } + return code; + } ++ ++void ++opvp_activate_path_control(gs_memory_t *mem, int enable) ++{ ++ gs_lib_ctx_core_t *core; ++ ++ if (mem == NULL || mem->gs_lib_ctx == NULL || ++ (core = mem->gs_lib_ctx->core) == NULL) ++ return; ++ ++ core->opvp_path_control_active = enable; ++} ++ ++int ++opvp_is_path_control_active(const gs_memory_t *mem) ++{ ++ gs_lib_ctx_core_t *core; ++ ++ if (mem == NULL || mem->gs_lib_ctx == NULL || ++ (core = mem->gs_lib_ctx->core) == NULL) ++ return 0; ++ ++ return core->opvp_path_control_active; ++} +diff --git a/base/gslibctx.h b/base/gslibctx.h +index 1481cb5..e4b3924 100644 +--- a/base/gslibctx.h ++++ b/base/gslibctx.h +@@ -61,6 +61,8 @@ typedef struct { + bool CPSI_mode; + int scanconverter; + int act_on_uel; ++ ++ int opvp_path_control_active; + } gs_lib_ctx_core_t; + + typedef struct gs_lib_ctx_s +@@ -167,4 +169,10 @@ int sjpxd_create(gs_memory_t *mem); + + void sjpxd_destroy(gs_memory_t *mem); + ++void ++opvp_activate_path_control(gs_memory_t *mem, int enable); ++ ++int ++opvp_is_path_control_active(const gs_memory_t *mem); ++ + #endif /* GSLIBCTX_H */ +diff --git a/contrib/opvp/gdevopvp.c b/contrib/opvp/gdevopvp.c +index 9a6b45b..9693673 100644 +--- a/contrib/opvp/gdevopvp.c ++++ b/contrib/opvp/gdevopvp.c +@@ -185,7 +185,7 @@ static int opvp_copy_color(gx_device *, const byte *, int, int, + static int _get_params(gs_param_list *); + static int opvp_get_params(gx_device *, gs_param_list *); + static int oprp_get_params(gx_device *, gs_param_list *); +-static int _put_params(gs_param_list *); ++static int _put_params(gx_device *, gs_param_list *); + static int opvp_put_params(gx_device *, gs_param_list *); + static int oprp_put_params(gx_device *, gs_param_list *); + static int opvp_fill_path(gx_device *, const gs_gstate *, gx_path *, +@@ -3039,7 +3039,7 @@ _get_params(gs_param_list *plist) + /* vector driver name */ + pname = "Driver"; + vdps.data = (byte *)vectorDriver; +- vdps.size = (vectorDriver ? strlen(vectorDriver) + 1 : 0); ++ vdps.size = (vectorDriver ? strlen(vectorDriver) : 0); + vdps.persistent = false; + code = param_write_string(plist, pname, &vdps); + if (code) ecode = code; +@@ -3176,7 +3176,7 @@ oprp_get_params(gx_device *dev, gs_param_list *plist) + * put params + */ + static int +-_put_params(gs_param_list *plist) ++_put_params(gx_device *dev, gs_param_list *plist) + { + int code; + int ecode = 0; +@@ -3198,6 +3198,12 @@ _put_params(gs_param_list *plist) + code = param_read_string(plist, pname, &vdps); + switch (code) { + case 0: ++ if (opvp_is_path_control_active(dev->memory) ++ && (!vectorDriver || strlen(vectorDriver) != vdps.size ++ || memcmp(vectorDriver, vdps.data, vdps.size) != 0)) { ++ param_signal_error(plist, pname, gs_error_invalidaccess); ++ return_error(gs_error_invalidaccess); ++ } + buff = realloc(buff, vdps.size + 1); + memcpy(buff, vdps.data, vdps.size); + buff[vdps.size] = 0; +@@ -3399,7 +3405,7 @@ opvp_put_params(gx_device *dev, gs_param_list *plist) + int code; + + /* put params */ +- code = _put_params(plist); ++ code = _put_params(dev, plist); + if (code) return code; + + /* put default params */ +@@ -3415,7 +3421,7 @@ oprp_put_params(gx_device *dev, gs_param_list *plist) + int code; + + /* put params */ +- code = _put_params(plist); ++ code = _put_params(dev, plist); + if (code) return code; + + /* put default params */ +diff --git a/psi/zfile.c b/psi/zfile.c +index 271a1a0..05b8203 100644 +--- a/psi/zfile.c ++++ b/psi/zfile.c +@@ -875,6 +875,12 @@ static int zgetfilename(i_ctx_t *i_ctx_p) + return 0; + } + ++static int zopvpactivatepathcontrol(i_ctx_t *i_ctx_p) ++{ ++ opvp_activate_path_control(imemory, 1); ++ return 0; ++} ++ + /* ------ Initialization procedure ------ */ + + const op_def zfile_op_defs[] = +@@ -893,6 +899,7 @@ const op_def zfile_op_defs[] = + {"0%file_continue", file_continue}, + {"0%execfile_finish", execfile_finish}, + {"1.getfilename", zgetfilename}, ++ {"0.opvpactivatepathcontrol", zopvpactivatepathcontrol}, + op_def_end(0) + }; +