diff --git a/CVE-2022-4515.patch b/CVE-2022-4515.patch new file mode 100644 index 0000000..18df621 --- /dev/null +++ b/CVE-2022-4515.patch @@ -0,0 +1,209 @@ +Based on +From e00c55d7a0204dc1d0ae316141323959e1e16162 Mon Sep 17 00:00:00 2001 +From: Masatake YAMATO +Date: Mon, 24 Oct 2016 23:52:23 +0900 +Subject: [PATCH] main: quote output file name before passing it to system(3) + function + +Following command line doesn't work: + + $ ctags -o 'a b' ... + +because a shell lauched from system(3) deals a whitespace between 'a' +and 'b' as a separator. The output file name is passed to system(3) +to run external sort command. + +This commit adds code to put double and single quoets around the output +file name before passing it to system(3). + +The issue is reported by Lorenz Hipp in a private mail. + +Signed-off-by: Masatake YAMATO +--- + Tmain/abnormal-output-file-names.d/input.c | 1 + + Tmain/abnormal-output-file-names.d/run.sh | 39 ++++++++++ + .../stderr-expected.txt | 0 + .../stdout-expected.txt | 8 +++ + main/sort.c | 72 ++++++++++++++----- + 5 files changed, 102 insertions(+), 18 deletions(-) + create mode 100644 Tmain/abnormal-output-file-names.d/input.c + create mode 100644 Tmain/abnormal-output-file-names.d/run.sh + create mode 100644 Tmain/abnormal-output-file-names.d/stderr-expected.txt + create mode 100644 Tmain/abnormal-output-file-names.d/stdout-expected.txt + +Index: ctags-5.8/Tmain/abnormal-output-file-names.d/input.c +=================================================================== +--- /dev/null ++++ ctags-5.8/Tmain/abnormal-output-file-names.d/input.c +@@ -0,0 +1 @@ ++int x; +Index: ctags-5.8/Tmain/abnormal-output-file-names.d/run.sh +=================================================================== +--- /dev/null ++++ ctags-5.8/Tmain/abnormal-output-file-names.d/run.sh +@@ -0,0 +1,39 @@ ++# Copyright: 2016 Masatake YAMATO ++# License: GPL-2 ++ ++CTAGS=$1 ++ ++rm -f ./"'" ++rm -f ./'"' ++rm -f ./'$(ls)' ++rm -f ./'a b' ++ ++${CTAGS} --options=NONE -o ./"'" --extra=-pF input.c ++${CTAGS} --options=NONE -o ./'"' --extra=-pF input.c ++${CTAGS} --options=NONE -o ./'$(ls)' --extra=-pF input.c ++${CTAGS} --options=NONE -o ./'a b' --extra=-pF input.c ++ ++echo '#' SINGLE QUOTE ++if [ -e "'" ]; then ++ cat "'" ++fi ++ ++echo '#' DOUBLE QUOTES ++if [ -e '"' ]; then ++ cat '"' ++fi ++ ++echo '#' PROCESS SUBSTITUTION ++if [ -e '$(ls)' ]; then ++ cat '$(ls)' ++fi ++ ++echo '#' SPACE ++if [ -e 'a b' ]; then ++ cat 'a b' ++fi ++ ++rm -f ./"'" ++rm -f ./'"' ++rm -f ./'$(ls)' ++rm -f ./'a b' +Index: ctags-5.8/Tmain/abnormal-output-file-names.d/stdout-expected.txt +=================================================================== +--- /dev/null ++++ ctags-5.8/Tmain/abnormal-output-file-names.d/stdout-expected.txt +@@ -0,0 +1,8 @@ ++# SINGLE QUOTE ++x input.c /^int x;$/;" v typeref:typename:int ++# DOUBLE QUOTES ++x input.c /^int x;$/;" v typeref:typename:int ++# PROCESS SUBSTITUTION ++x input.c /^int x;$/;" v typeref:typename:int ++# SPACE ++x input.c /^int x;$/;" v typeref:typename:int +Index: ctags-5.8/sort.c +=================================================================== +--- ctags-5.8.orig/sort.c ++++ ctags-5.8/sort.c +@@ -19,6 +19,7 @@ + #endif + #include + #include ++#include + + #include "debug.h" + #include "entry.h" +@@ -53,41 +54,83 @@ extern void catFile (const char *const n + # define PE_CONST const + #endif + ++/* ++ Output file name should not be evaluated in system(3) function. ++ The name must be used as is. Quotations are required to block the ++ evaluation. ++ ++ Normal single-quotes are used to quote a cstring: ++ a => 'a' ++ " => '"' ++ ++ If a single-quote is included in the cstring, use double quotes for quoting it. ++ ' => ''"'"'' ++*/ ++static void appendCstringWithQuotes (vString *dest, const char* cstr) ++{ ++ const char* o; ++ ++ vStringPut (dest, '\''); ++ for (o = cstr; *o; o++) ++ { ++ if (*o == '\'') ++ vStringCatS (dest, "'\"'\"'"); ++ else ++ vStringPut (dest, *o); ++ } ++ vStringPut (dest, '\''); ++} ++ + extern void externalSortTags (const boolean toStdout) + { +- const char *const sortNormalCommand = "sort -u -o"; +- const char *const sortFoldedCommand = "sort -u -f -o"; ++ const char *const sortNormalCommand = "/usr/bin/sort -u"; ++ const char *const sortFoldedCommand = "/usr/bin/sort -u -f"; + const char *sortCommand = + Option.sorted == SO_FOLDSORTED ? sortFoldedCommand : sortNormalCommand; ++# ifndef HAVE_SETENV + PE_CONST char *const sortOrder1 = "LC_COLLATE=C"; + PE_CONST char *const sortOrder2 = "LC_ALL=C"; +- const size_t length = 4 + strlen (sortOrder1) + strlen (sortOrder2) + +- strlen (sortCommand) + (2 * strlen (tagFileName ())); +- char *const cmd = (char *) malloc (length + 1); ++# endif ++ vString *cmd = vStringNew (); + int ret = -1; + + if (cmd != NULL) + { + /* Ensure ASCII value sort order. + */ +-#ifdef HAVE_SETENV ++#if defined(HAVE_SETENV) || defined(HAVE_PUTENV) ++# if HAVE_SETENV + setenv ("LC_COLLATE", "C", 1); + setenv ("LC_ALL", "C", 1); +- sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ()); +-#else +-# ifdef HAVE_PUTENV ++# else + putenv (sortOrder1); + putenv (sortOrder2); +- sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ()); +-# else +- sprintf (cmd, "%s %s %s %s %s", sortOrder1, sortOrder2, sortCommand, +- tagFileName (), tagFileName ()); + # endif ++ vStringCatS (cmd, sortCommand); ++// if (! toStdout) ++ { ++ vStringCatS (cmd, " -o "); ++ appendCstringWithQuotes (cmd, tagFileName ()); ++ vStringPut (cmd, ' '); ++ appendCstringWithQuotes (cmd, tagFileName ()); ++ } ++#else ++ vStringCatS (cmd, sortOrder1); ++ vStringPut (cmd, ' '); ++ vStringCatS (cmd, sortOrder2); ++ vStringPut (cmd, ' '); ++ vStringCatS (cmd, sortCommand); ++// if (! toStdout) ++ { ++ vStringCats (cmd, " -o "); ++ appendCstringWithQuotes (cmd, tagFileName ()); ++ vStringPut (cmd, ' '); ++ appendCstringWithQuotes (cmd, tagFileName ()); ++ } + #endif +- verbose ("system (\"%s\")\n", cmd); +- ret = system (cmd); +- free (cmd); +- ++ verbose ("system (\"%s\")\n", vStringValue(cmd)); ++ ret = system (vStringValue(cmd)); ++ vStringDelete (cmd); + } + if (ret != 0) + error (FATAL | PERROR, "cannot sort tag file"); diff --git a/ctags.changes b/ctags.changes index 9103e2e..f7a2e15 100644 --- a/ctags.changes +++ b/ctags.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Wed Jan 18 13:15:03 UTC 2023 - Adam Majer + +- + +------------------------------------------------------------------- +Wed Jan 18 13:06:30 UTC 2023 - Adam Majer + +- CVE-2022-4515.patch: fixes arbitrary command execution via + a tag file with a crafted filename (bsc#1206543, CVE-2022-4515) +- Stop resetting ctags update-alternative priority back to auto. + These are admin settings. + ------------------------------------------------------------------- Mon Sep 27 08:59:35 UTC 2021 - Michal Suchanek diff --git a/ctags.spec b/ctags.spec index 8876a0a..856f3eb 100644 --- a/ctags.spec +++ b/ctags.spec @@ -1,7 +1,7 @@ # # spec file for package ctags # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -47,6 +47,7 @@ Patch17: 0017-Go-language-support.patch Patch18: 0018-SUSE-man-page-changes.patch Patch19: 0019-Do-not-include-build-time-in-binary.patch Patch20: ctags-gcc11.patch +Patch21: CVE-2022-4515.patch BuildRequires: update-alternatives Requires(pre): update-alternatives Requires(post): update-alternatives @@ -86,7 +87,6 @@ ln -s %{_mandir}/man1/ctags.1%{ext_man} %{buildroot}%{_sysconfdir}/ test -L %{_bindir}/ctags || rm -f %{_bindir}/ctags update-alternatives --install %{_bindir}/ctags ctags %{_bindir}/ctags-exuberant 20 \ --slave %{_mandir}/man1/ctags.1.gz ctags.1 %{_mandir}/man1/ctags-exuberant.1.gz -update-alternatives --auto ctags %preun if [ $1 -eq 0 ]; then