git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees()
@ 2021-03-17 15:30 Johannes Schindelin via GitGitGadget
  2021-03-17 15:30 ` [PATCH 1/2] fsmonitor: fix memory corruption in some corner cases Johannes Schindelin via GitGitGadget
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2021-03-17 15:30 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin

While dog-fooding Jeff Hostetler's FSMonitor patches, I ran into a really
obscure segmentation fault during one of my epic Git for Windows rebases.
Turns out that this bug is quite old.

Johannes Schindelin (2):
  fsmonitor: fix memory corruption in some corner cases
  fsmonitor: do not forget to release the token in `discard_index()`

 read-cache.c   | 1 +
 unpack-trees.c | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)


base-commit: dfaed028620c2dca08d24583c7fc8b0aef9b6d0f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-891%2Fdscho%2Ffix-fsmonitor-crash-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-891/dscho/fix-fsmonitor-crash-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/891
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] fsmonitor: fix memory corruption in some corner cases
  2021-03-17 15:30 [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Johannes Schindelin via GitGitGadget
@ 2021-03-17 15:30 ` Johannes Schindelin via GitGitGadget
  2021-03-17 19:19   ` Junio C Hamano
  2021-03-17 15:30 ` [PATCH 2/2] fsmonitor: do not forget to release the token in `discard_index()` Johannes Schindelin via GitGitGadget
  2021-03-17 20:21 ` [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Derrick Stolee
  2 siblings, 1 reply; 6+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2021-03-17 15:30 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Johannes Schindelin

From: Johannes Schindelin <johannes.schindelin@gmx.de>

In 56c6910028a (fsmonitor: change last update timestamp on the
index_state to opaque token, 2020-01-07), we forgot to adjust the part
of `unpack_trees()` that copies the FSMonitor "last-update" information
that we copy from the source index to the result index since 679f2f9fdd2
(unpack-trees: skip stat on fsmonitor-valid files, 2019-11-20).

Since the "last-update" information is no longer a 64-bit number, but a
free-form string that has been allocated, we need to duplicate it rather
than just copying it.

This is important because there _are_ cases when `unpack_trees()` will
perform a oneway merge that implicitly calls `refresh_fsmonitor()`
(which will allocate that "last-update" token). This happens _after_
that token was copied into the result index. However, we _then_ call
`check_updates()` on that index, which will _also_ call
`refresh_fsmonitor()`, accessing the "last-update" string, which by now
would be released already.

In the instance that lead to this patch, this caused a segmentation
fault during a lengthy, complicated rebase involving the todo command
`reset` that (crucially) had to updated many files. Unfortunately, it
seems very hard to trigger that crash, therefore this patch is not
accompanied by a regression test.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 unpack-trees.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/unpack-trees.c b/unpack-trees.c
index 2399b6818be6..63e3d961b378 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1544,8 +1544,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 	o->merge_size = len;
 	mark_all_ce_unused(o->src_index);
 
-	if (o->src_index->fsmonitor_last_update)
-		o->result.fsmonitor_last_update = o->src_index->fsmonitor_last_update;
+	o->result.fsmonitor_last_update =
+		xstrdup_or_null(o->src_index->fsmonitor_last_update);
 
 	/*
 	 * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] fsmonitor: do not forget to release the token in `discard_index()`
  2021-03-17 15:30 [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Johannes Schindelin via GitGitGadget
  2021-03-17 15:30 ` [PATCH 1/2] fsmonitor: fix memory corruption in some corner cases Johannes Schindelin via GitGitGadget
@ 2021-03-17 15:30 ` Johannes Schindelin via GitGitGadget
  2021-03-17 20:21 ` [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Derrick Stolee
  2 siblings, 0 replies; 6+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2021-03-17 15:30 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Johannes Schindelin

From: Johannes Schindelin <johannes.schindelin@gmx.de>

In 56c6910028a (fsmonitor: change last update timestamp on the
index_state to opaque token, 2020-01-07), we forgot to adjust
`discard_index()` to release the "last-update" token: it is no longer a
64-bit number, but a free-form string that has been allocated.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 read-cache.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/read-cache.c b/read-cache.c
index aa427c5c170f..cf5ff3158550 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2364,6 +2364,7 @@ int discard_index(struct index_state *istate)
 	cache_tree_free(&(istate->cache_tree));
 	istate->initialized = 0;
 	istate->fsmonitor_has_run_once = 0;
+	FREE_AND_NULL(istate->fsmonitor_last_update);
 	FREE_AND_NULL(istate->cache);
 	istate->cache_alloc = 0;
 	discard_split_index(istate);
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] fsmonitor: fix memory corruption in some corner cases
  2021-03-17 15:30 ` [PATCH 1/2] fsmonitor: fix memory corruption in some corner cases Johannes Schindelin via GitGitGadget
@ 2021-03-17 19:19   ` Junio C Hamano
  0 siblings, 0 replies; 6+ messages in thread
From: Junio C Hamano @ 2021-03-17 19:19 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget; +Cc: git, Johannes Schindelin

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> --- a/unpack-trees.c
> +++ b/unpack-trees.c
> @@ -1544,8 +1544,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
>  	o->merge_size = len;
>  	mark_all_ce_unused(o->src_index);
>  
> -	if (o->src_index->fsmonitor_last_update)
> -		o->result.fsmonitor_last_update = o->src_index->fsmonitor_last_update;
> +	o->result.fsmonitor_last_update =
> +		xstrdup_or_null(o->src_index->fsmonitor_last_update);

And this won't happen twice, so there is no need to free what is in
the o->result side before assignment.  And 2/2 frees it so we do not
leak at the end either.

Will queue; thanks.

>  
>  	/*
>  	 * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees()
  2021-03-17 15:30 [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Johannes Schindelin via GitGitGadget
  2021-03-17 15:30 ` [PATCH 1/2] fsmonitor: fix memory corruption in some corner cases Johannes Schindelin via GitGitGadget
  2021-03-17 15:30 ` [PATCH 2/2] fsmonitor: do not forget to release the token in `discard_index()` Johannes Schindelin via GitGitGadget
@ 2021-03-17 20:21 ` Derrick Stolee
  2021-03-19 14:49   ` Johannes Schindelin
  2 siblings, 1 reply; 6+ messages in thread
From: Derrick Stolee @ 2021-03-17 20:21 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget, git; +Cc: Johannes Schindelin

On 3/17/2021 11:30 AM, Johannes Schindelin via GitGitGadget wrote:
> While dog-fooding Jeff Hostetler's FSMonitor patches, I ran into a really
> obscure segmentation fault during one of my epic Git for Windows rebases.

Thanks for dogfooding!

> Turns out that this bug is quite old.

A little over a year, yes, since the v2 hook was committed. It's old
enough that these could be applied to 'maint'.
 
> Johannes Schindelin (2):
>   fsmonitor: fix memory corruption in some corner cases
>   fsmonitor: do not forget to release the token in `discard_index()`

The patches themselves are correct and describe the problem well.
They only show up during non-trivial uses of FS Monitor and index
updates, so I understand your hesitance to write tests that trigger
these problems.

Thanks,
-Stolee

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees()
  2021-03-17 20:21 ` [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Derrick Stolee
@ 2021-03-19 14:49   ` Johannes Schindelin
  0 siblings, 0 replies; 6+ messages in thread
From: Johannes Schindelin @ 2021-03-19 14:49 UTC (permalink / raw)
  To: Derrick Stolee; +Cc: Johannes Schindelin via GitGitGadget, git

Hi Stolee,

On Wed, 17 Mar 2021, Derrick Stolee wrote:

> On 3/17/2021 11:30 AM, Johannes Schindelin via GitGitGadget wrote:
> > While dog-fooding Jeff Hostetler's FSMonitor patches, I ran into a really
> > obscure segmentation fault during one of my epic Git for Windows rebases.
>
> Thanks for dogfooding!

I'm completely selfish here, as I want to benefit from the speed myself,
and that's also the reason why I added this as an experimental option to
Git for Windows v2.31.0: That way, I can test it everywhere (and so can
others).

> > Turns out that this bug is quite old.
>
> A little over a year, yes, since the v2 hook was committed. It's old
> enough that these could be applied to 'maint'.

Indeed. Even better: if you look closely at the GitGitGadget PR, you will
see that I based it on `kw/fsmonitor-watchman-racefix`.

> > Johannes Schindelin (2):
> >   fsmonitor: fix memory corruption in some corner cases
> >   fsmonitor: do not forget to release the token in `discard_index()`
>
> The patches themselves are correct and describe the problem well.
> They only show up during non-trivial uses of FS Monitor and index
> updates, so I understand your hesitance to write tests that trigger
> these problems.

Right. For me, I ran into them only in one specific instance, when
rebasing Git for Windows' patch thicket onto `seen`, and then only when
merging a topic branch with a rather big diff.

Thanks,
Dscho

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-03-19 14:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-17 15:30 [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Johannes Schindelin via GitGitGadget
2021-03-17 15:30 ` [PATCH 1/2] fsmonitor: fix memory corruption in some corner cases Johannes Schindelin via GitGitGadget
2021-03-17 19:19   ` Junio C Hamano
2021-03-17 15:30 ` [PATCH 2/2] fsmonitor: do not forget to release the token in `discard_index()` Johannes Schindelin via GitGitGadget
2021-03-17 20:21 ` [PATCH 0/2] Fix memory corruption with FSMonitor-enabled unpack_trees() Derrick Stolee
2021-03-19 14:49   ` Johannes Schindelin

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).