fix CVE-2024-43374
(cherry picked from commit 1c707897f2c7643f9dd1dd9423d16cc86aa1152f)
This commit is contained in:
parent
189a72e9da
commit
19d01b160a
300
backport-CVE-2024-43374.patch
Normal file
300
backport-CVE-2024-43374.patch
Normal file
@ -0,0 +1,300 @@
|
||||
From 0a6e57b09bc8c76691b367a5babfb79b31b770e8 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Brabandt <cb@256bit.org>
|
||||
Date: Thu, 15 Aug 2024 22:15:28 +0200
|
||||
Subject: [PATCH] patch 9.1.0678: [security]: use-after-free in alist_add()
|
||||
https://github.com/vim/vim/commit/0a6e57b09bc8c76691b367a5babfb79b31b770e8
|
||||
|
||||
Problem: [security]: use-after-free in alist_add()
|
||||
(SuyueGuo)
|
||||
Solution: Lock the current window, so that the reference to
|
||||
the argument list remains valid.
|
||||
|
||||
This fixes CVE-2024-43374
|
||||
|
||||
Signed-off-by: Christian Brabandt <cb@256bit.org>
|
||||
---
|
||||
src/arglist.c | 6 ++++++
|
||||
src/buffer.c | 4 ++--
|
||||
src/ex_cmds.c | 4 ++--
|
||||
src/proto/window.pro | 1 +
|
||||
src/structs.h | 2 +-
|
||||
src/terminal.c | 4 ++--
|
||||
src/testdir/test_arglist.vim | 23 +++++++++++++++++++++++
|
||||
src/version.c | 2 ++
|
||||
src/window.c | 29 +++++++++++++++++++----------
|
||||
9 files changed, 58 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/arglist.c b/src/arglist.c
|
||||
index a63f6c7..050f96f 100644
|
||||
--- a/src/arglist.c
|
||||
+++ b/src/arglist.c
|
||||
@@ -184,6 +184,8 @@ alist_set(
|
||||
/*
|
||||
* Add file "fname" to argument list "al".
|
||||
* "fname" must have been allocated and "al" must have been checked for room.
|
||||
+ *
|
||||
+ * May trigger Buf* autocommands
|
||||
*/
|
||||
void
|
||||
alist_add(
|
||||
@@ -196,6 +198,7 @@ alist_add(
|
||||
if (check_arglist_locked() == FAIL)
|
||||
return;
|
||||
arglist_locked = TRUE;
|
||||
+ curwin->w_locked = TRUE;
|
||||
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
slash_adjust(fname);
|
||||
@@ -207,6 +210,7 @@ alist_add(
|
||||
++al->al_ga.ga_len;
|
||||
|
||||
arglist_locked = FALSE;
|
||||
+ curwin->w_locked = FALSE;
|
||||
}
|
||||
|
||||
#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
|
||||
@@ -365,6 +369,7 @@ alist_add_list(
|
||||
mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
|
||||
(ARGCOUNT - after) * sizeof(aentry_T));
|
||||
arglist_locked = TRUE;
|
||||
+ curwin->w_locked = TRUE;
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
int flags = BLN_LISTED | (will_edit ? BLN_CURBUF : 0);
|
||||
@@ -373,6 +378,7 @@ alist_add_list(
|
||||
ARGLIST[after + i].ae_fnum = buflist_add(files[i], flags);
|
||||
}
|
||||
arglist_locked = FALSE;
|
||||
+ curwin->w_locked = FALSE;
|
||||
ALIST(curwin)->al_ga.ga_len += count;
|
||||
if (old_argcount > 0 && curwin->w_arg_idx >= after)
|
||||
curwin->w_arg_idx += count;
|
||||
diff --git a/src/buffer.c b/src/buffer.c
|
||||
index ccd095b..260d22e 100644
|
||||
--- a/src/buffer.c
|
||||
+++ b/src/buffer.c
|
||||
@@ -1456,7 +1456,7 @@ do_buffer_ext(
|
||||
// (unless it's the only window). Repeat this so long as we end up in
|
||||
// a window with this buffer.
|
||||
while (buf == curbuf
|
||||
- && !(curwin->w_closing || curwin->w_buffer->b_locked > 0)
|
||||
+ && !(win_locked(curwin) || curwin->w_buffer->b_locked > 0)
|
||||
&& (!ONE_WINDOW || first_tabpage->tp_next != NULL))
|
||||
{
|
||||
if (win_close(curwin, FALSE) == FAIL)
|
||||
@@ -5443,7 +5443,7 @@ ex_buffer_all(exarg_T *eap)
|
||||
: wp->w_width != Columns)
|
||||
|| (had_tab > 0 && wp != firstwin))
|
||||
&& !ONE_WINDOW
|
||||
- && !(wp->w_closing || wp->w_buffer->b_locked > 0)
|
||||
+ && !(win_locked(wp) || wp->w_buffer->b_locked > 0)
|
||||
&& !win_unlisted(wp))
|
||||
{
|
||||
if (win_close(wp, FALSE) == FAIL)
|
||||
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
|
||||
index a08682b..46c4503 100644
|
||||
--- a/src/ex_cmds.c
|
||||
+++ b/src/ex_cmds.c
|
||||
@@ -2827,7 +2827,7 @@ do_ecmd(
|
||||
|
||||
// Set the w_closing flag to avoid that autocommands close the
|
||||
// window. And set b_locked for the same reason.
|
||||
- the_curwin->w_closing = TRUE;
|
||||
+ the_curwin->w_locked = TRUE;
|
||||
++buf->b_locked;
|
||||
|
||||
if (curbuf == old_curbuf.br_buf)
|
||||
@@ -2841,7 +2841,7 @@ do_ecmd(
|
||||
|
||||
// Autocommands may have closed the window.
|
||||
if (win_valid(the_curwin))
|
||||
- the_curwin->w_closing = FALSE;
|
||||
+ the_curwin->w_locked = FALSE;
|
||||
--buf->b_locked;
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
diff --git a/src/proto/window.pro b/src/proto/window.pro
|
||||
index cfb771d..12edf0b 100644
|
||||
--- a/src/proto/window.pro
|
||||
+++ b/src/proto/window.pro
|
||||
@@ -93,4 +93,5 @@ int win_hasvertsplit(void);
|
||||
int get_win_number(win_T *wp, win_T *first_win);
|
||||
int get_tab_number(tabpage_T *tp);
|
||||
char *check_colorcolumn(win_T *wp);
|
||||
+int win_locked(win_T *wp);
|
||||
/* vim: set ft=c : */
|
||||
diff --git a/src/structs.h b/src/structs.h
|
||||
index 6d9dcbb..1f4742b 100644
|
||||
--- a/src/structs.h
|
||||
+++ b/src/structs.h
|
||||
@@ -3740,7 +3740,7 @@ struct window_S
|
||||
synblock_T *w_s; // for :ownsyntax
|
||||
#endif
|
||||
|
||||
- int w_closing; // window is being closed, don't let
|
||||
+ int w_locked; // window is being closed, don't let
|
||||
// autocommands close it too.
|
||||
|
||||
frame_T *w_frame; // frame containing this window
|
||||
diff --git a/src/terminal.c b/src/terminal.c
|
||||
index f79d102..37cd0f2 100644
|
||||
--- a/src/terminal.c
|
||||
+++ b/src/terminal.c
|
||||
@@ -3669,10 +3669,10 @@ term_after_channel_closed(term_T *term)
|
||||
if (is_aucmd_win(curwin))
|
||||
do_set_w_closing = TRUE;
|
||||
if (do_set_w_closing)
|
||||
- curwin->w_closing = TRUE;
|
||||
+ curwin->w_locked = TRUE;
|
||||
do_bufdel(DOBUF_WIPE, (char_u *)"", 1, fnum, fnum, FALSE);
|
||||
if (do_set_w_closing)
|
||||
- curwin->w_closing = FALSE;
|
||||
+ curwin->w_locked = FALSE;
|
||||
aucmd_restbuf(&aco);
|
||||
}
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
diff --git a/src/testdir/test_arglist.vim b/src/testdir/test_arglist.vim
|
||||
index edc8b77..8d81a82 100644
|
||||
--- a/src/testdir/test_arglist.vim
|
||||
+++ b/src/testdir/test_arglist.vim
|
||||
@@ -359,6 +359,7 @@ func Test_argv()
|
||||
call assert_equal('', argv(1, 100))
|
||||
call assert_equal([], argv(-1, 100))
|
||||
call assert_equal('', argv(10, -1))
|
||||
+ %argdelete
|
||||
endfunc
|
||||
|
||||
" Test for the :argedit command
|
||||
@@ -744,4 +745,26 @@ func Test_all_command()
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
+" Test for deleting buffer when creating an arglist. This was accessing freed
|
||||
+" memory
|
||||
+func Test_crash_arglist_uaf()
|
||||
+ "%argdelete
|
||||
+ new one
|
||||
+ au BufAdd XUAFlocal :bw
|
||||
+ "call assert_fails(':arglocal XUAFlocal', 'E163:')
|
||||
+ arglocal XUAFlocal
|
||||
+ au! BufAdd
|
||||
+ bw! XUAFlocal
|
||||
+
|
||||
+ au BufAdd XUAFlocal2 :bw
|
||||
+ new two
|
||||
+ new three
|
||||
+ arglocal
|
||||
+ argadd XUAFlocal2 Xfoobar
|
||||
+ bw! XUAFlocal2
|
||||
+ bw! two
|
||||
+
|
||||
+ au! BufAdd
|
||||
+endfunc
|
||||
+
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
diff --git a/src/version.c b/src/version.c
|
||||
index 555ef9f..10916ed 100644
|
||||
--- a/src/version.c
|
||||
+++ b/src/version.c
|
||||
@@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
+/**/
|
||||
+ 678,
|
||||
/**/
|
||||
2092,
|
||||
/**/
|
||||
diff --git a/src/window.c b/src/window.c
|
||||
index 2afa28d..e2a7393 100644
|
||||
--- a/src/window.c
|
||||
+++ b/src/window.c
|
||||
@@ -2441,7 +2441,7 @@ close_windows(
|
||||
for (wp = firstwin; wp != NULL && !ONE_WINDOW; )
|
||||
{
|
||||
if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)
|
||||
- && !(wp->w_closing || wp->w_buffer->b_locked > 0))
|
||||
+ && !(win_locked(wp) || wp->w_buffer->b_locked > 0))
|
||||
{
|
||||
if (win_close(wp, FALSE) == FAIL)
|
||||
// If closing the window fails give up, to avoid looping
|
||||
@@ -2462,7 +2462,7 @@ close_windows(
|
||||
if (tp != curtab)
|
||||
FOR_ALL_WINDOWS_IN_TAB(tp, wp)
|
||||
if (wp->w_buffer == buf
|
||||
- && !(wp->w_closing || wp->w_buffer->b_locked > 0))
|
||||
+ && !(win_locked(wp) || wp->w_buffer->b_locked > 0))
|
||||
{
|
||||
win_close_othertab(wp, FALSE, tp);
|
||||
|
||||
@@ -2584,10 +2584,10 @@ win_close_buffer(win_T *win, int action, int abort_if_last)
|
||||
bufref_T bufref;
|
||||
|
||||
set_bufref(&bufref, curbuf);
|
||||
- win->w_closing = TRUE;
|
||||
+ win->w_locked = TRUE;
|
||||
close_buffer(win, win->w_buffer, action, abort_if_last, TRUE);
|
||||
if (win_valid_any_tab(win))
|
||||
- win->w_closing = FALSE;
|
||||
+ win->w_locked = FALSE;
|
||||
// Make sure curbuf is valid. It can become invalid if 'bufhidden' is
|
||||
// "wipe".
|
||||
if (!bufref_valid(&bufref))
|
||||
@@ -2635,7 +2635,7 @@ win_close(win_T *win, int free_buf)
|
||||
if (window_layout_locked(CMD_close))
|
||||
return FAIL;
|
||||
|
||||
- if (win->w_closing || (win->w_buffer != NULL
|
||||
+ if (win_locked(win) || (win->w_buffer != NULL
|
||||
&& win->w_buffer->b_locked > 0))
|
||||
return FAIL; // window is already being closed
|
||||
if (win_unlisted(win))
|
||||
@@ -2684,19 +2684,19 @@ win_close(win_T *win, int free_buf)
|
||||
other_buffer = TRUE;
|
||||
if (!win_valid(win))
|
||||
return FAIL;
|
||||
- win->w_closing = TRUE;
|
||||
+ win->w_locked = TRUE;
|
||||
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
|
||||
if (!win_valid(win))
|
||||
return FAIL;
|
||||
- win->w_closing = FALSE;
|
||||
+ win->w_locked = FALSE;
|
||||
if (last_window())
|
||||
return FAIL;
|
||||
}
|
||||
- win->w_closing = TRUE;
|
||||
+ win->w_locked = TRUE;
|
||||
apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
|
||||
if (!win_valid(win))
|
||||
return FAIL;
|
||||
- win->w_closing = FALSE;
|
||||
+ win->w_locked = FALSE;
|
||||
if (last_window())
|
||||
return FAIL;
|
||||
#ifdef FEAT_EVAL
|
||||
@@ -3269,7 +3269,7 @@ win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
|
||||
|
||||
// Get here with win->w_buffer == NULL when win_close() detects the tab
|
||||
// page changed.
|
||||
- if (win->w_closing || (win->w_buffer != NULL
|
||||
+ if (win_locked(win) || (win->w_buffer != NULL
|
||||
&& win->w_buffer->b_locked > 0))
|
||||
return; // window is already being closed
|
||||
|
||||
@@ -7792,3 +7792,12 @@ skip:
|
||||
return NULL; // no error
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+/*
|
||||
+ * Don't let autocommands close the given window
|
||||
+ */
|
||||
+ int
|
||||
+win_locked(win_T *wp)
|
||||
+{
|
||||
+ return wp->w_locked;
|
||||
+}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
9
vim.spec
9
vim.spec
@ -14,7 +14,7 @@
|
||||
Name: vim
|
||||
Epoch: 2
|
||||
Version: %{baseversion}.%{patchlevel}
|
||||
Release: 8
|
||||
Release: 9
|
||||
Summary: Vim is a highly configurable text editor for efficiently creating and changing any kind of text.
|
||||
License: Vim and MIT
|
||||
URL: http://www.vim.org
|
||||
@ -47,6 +47,7 @@ Patch6013: backport-patch-9.1.0267-File-name-entered-in-GUI-dialog-is-ig.pa
|
||||
Patch6014: backport-CVE-2024-41965.patch
|
||||
Patch6015: backport-patch-9.1.0554-bw-leaves-jumplist-and-tagstack-data-.patch
|
||||
Patch6016: backport-CVE-2024-41957.patch
|
||||
Patch6017: backport-CVE-2024-43374.patch
|
||||
|
||||
Patch9000: bugfix-rm-modify-info-version.patch
|
||||
|
||||
@ -454,6 +455,12 @@ LC_ALL=en_US.UTF-8 make -j1 test || echo "Warning: Please check tests."
|
||||
%{_mandir}/man1/evim.*
|
||||
|
||||
%changelog
|
||||
* Fri Aug 16 2024 zhangxianting <zhangxianting@uniontech.com> - 2:9.0.2092-9
|
||||
- Type:CVE
|
||||
- ID:CVE-2024-43374
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2024-43374
|
||||
|
||||
* Tue Aug 06 2024 wangjiang <wangjiang37@h-partners.com> - 2:9.0.2092-8
|
||||
- Type:CVE
|
||||
- ID:CVE-2024-41957 CVE-2024-41965
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user