diff --git a/emacs-etags-local-command-injection-vulnerability.patch b/emacs-etags-local-command-injection-vulnerability.patch new file mode 100644 index 0000000..418b7d7 --- /dev/null +++ b/emacs-etags-local-command-injection-vulnerability.patch @@ -0,0 +1,105 @@ +From 01a4035c869b91c153af9a9132c87adb7669ea1c Mon Sep 17 00:00:00 2001 +From: lu4nx +Date: Tue, 6 Dec 2022 15:42:40 +0800 +Subject: [PATCH] Fix etags local command injection vulnerability + +* lib-src/etags.c: (escape_shell_arg_string): New function. +(process_file_name): Use it to quote file names passed to the +shell. (Bug#59817) +--- + lib-src/etags.c | 63 +++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 58 insertions(+), 5 deletions(-) + +diff --git a/lib-src/etags.c b/lib-src/etags.c +index d1d20858cdd..ba0092cc637 100644 +--- a/lib-src/etags.c ++++ b/lib-src/etags.c +@@ -399,6 +399,7 @@ static void put_entries (node *); + static void clean_matched_file_tag (char const * const, char const * const); + + static void do_move_file (const char *, const char *); ++static char *escape_shell_arg_string (char *); + static char *concat (const char *, const char *, const char *); + static char *skip_spaces (char *); + static char *skip_non_spaces (char *); +@@ -1670,13 +1671,16 @@ process_file_name (char *file, language *lang) + else + { + #if MSDOS || defined (DOS_NT) +- char *cmd1 = concat (compr->command, " \"", real_name); +- char *cmd = concat (cmd1, "\" > ", tmp_name); ++ int buf_len = strlen (compr->command) + strlen (" \"\" > \"\"") + strlen (real_name) + strlen (tmp_name) + 1; ++ char *cmd = xmalloc (buf_len); ++ snprintf (cmd, buf_len, "%s \"%s\" > \"%s\"", compr->command, real_name, tmp_name); + #else +- char *cmd1 = concat (compr->command, " '", real_name); +- char *cmd = concat (cmd1, "' > ", tmp_name); ++ char *new_real_name = escape_shell_arg_string (real_name); ++ char *new_tmp_name = escape_shell_arg_string (tmp_name); ++ int buf_len = strlen (compr->command) + strlen (" > ") + strlen (new_real_name) + strlen (new_tmp_name) + 1; ++ char *cmd = xmalloc (buf_len); ++ snprintf (cmd, buf_len, "%s %s > %s", compr->command, new_real_name, new_tmp_name); + #endif +- free (cmd1); + int tmp_errno; + if (system (cmd) == -1) + { +@@ -7124,6 +7128,55 @@ etags_mktmp (void) + return templt; + } + ++/* ++ * Adds single quotes around a string, if found single quotes, escaped it. ++ * Return a newly-allocated string. ++ * ++ * For example: ++ * escape_shell_arg_string("test.txt") => 'test.txt' ++ * escape_shell_arg_string("'test.txt") => ''\''test.txt' ++ */ ++static char * ++escape_shell_arg_string (char *str) ++{ ++ char *p = str; ++ int need_space = 2; /* ' at begin and end */ ++ ++ while (*p != '\0') ++ { ++ if (*p == '\'') ++ need_space += 4; /* ' to '\'', length is 4 */ ++ else ++ need_space++; ++ ++ p++; ++ } ++ ++ char *new_str = xnew (need_space + 1, char); ++ new_str[0] = '\''; ++ new_str[need_space-1] = '\''; ++ ++ int i = 1; /* skip first byte */ ++ p = str; ++ while (*p != '\0') ++ { ++ new_str[i] = *p; ++ if (*p == '\'') ++ { ++ new_str[i+1] = '\\'; ++ new_str[i+2] = '\''; ++ new_str[i+3] = '\''; ++ i += 3; ++ } ++ ++ i++; ++ p++; ++ } ++ ++ new_str[need_space] = '\0'; ++ return new_str; ++} ++ + static void + do_move_file(const char *src_file, const char *dst_file) + { +-- +2.36.1 + diff --git a/emacs.spec b/emacs.spec index 1bcc215..b7a64eb 100644 --- a/emacs.spec +++ b/emacs.spec @@ -29,6 +29,7 @@ Patch2: emacs-system-crypto-policies.patch Patch3: emacs-glibc-2.34.patch Patch4: emacs-ctags-local-command-execute-vulnerability.patch Patch5: emacs-64KB-page-size-for-pdump.patch +Patch6: emacs-etags-local-command-injection-vulnerability.patch BuildRequires: gcc BuildRequires: atk-devel BuildRequires: cairo-devel @@ -193,6 +194,7 @@ Development header files for Emacs. %patch3 -p1 -b .glibc2.34 %patch4 -p1 -b .ctags-local-command-execute-vulnerability %patch5 -p1 -b .64KB-page-size-for-pdump +%patch6 -p1 -b .etags-local-command-injection-vulnerability autoconf # We prefer our emacs.desktop file