git-commit-vandalism/builtin
Ævar Arnfjörð Bjarmason a8cc594333 hooks: fix an obscure TOCTOU "did we just run a hook?" race
Fix a Time-of-check to time-of-use (TOCTOU) race in code added in
680ee550d7 (commit: skip discarding the index if there is no
pre-commit hook, 2017-08-14).

This obscure race condition can occur if we e.g. ran the "pre-commit"
hook and it modified the index, but hook_exists() returns false later
on (e.g., because the hook itself went away, the directory became
unreadable, etc.). Then we won't call discard_cache() when we should
have.

The race condition itself probably doesn't matter, and users would
have been unlikely to run into it in practice. This problem has been
noted on-list when 680ee550d7 was discussed[1], but had not been
fixed.

This change is mainly intended to improve the readability of the code
involved, and to make reasoning about it more straightforward. It
wasn't as obvious what we were trying to do here, but by having an
"invoked_hook" it's clearer that e.g. our discard_cache() is happening
because of the earlier hook execution.

Let's also change this for the push-to-checkout hook. Now instead of
checking if the hook exists and either doing a push to checkout or a
push to deploy we'll always attempt a push to checkout. If the hook
doesn't exist we'll fall back on push to deploy. The same behavior as
before, without the TOCTOU race. See 0855331941 (receive-pack:
support push-to-checkout hook, 2014-12-01) for the introduction of the
previous behavior.

This leaves uses of hook_exists() in two places that matter. The
"reference-transaction" check in refs.c, see 6754159767 (refs:
implement reference transaction hook, 2020-06-19), and the
"prepare-commit-msg" hook, see 66618a50f9 (sequencer: run
'prepare-commit-msg' hook, 2018-01-24).

In both of those cases we're saving ourselves CPU time by not
preparing data for the hook that we'll then do nothing with if we
don't have the hook. So using this "invoked_hook" pattern doesn't make
sense in those cases.

The "reference-transaction" and "prepare-commit-msg" hook also aren't
racy. In those cases we'll skip the hook runs if we race with a new
hook being added, whereas in the TOCTOU races being fixed here we were
incorrectly skipping the required post-hook logic.

1. https://lore.kernel.org/git/20170810191613.kpmhzg4seyxy3cpq@sigill.intra.peff.net/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-03-07 13:00:53 -08:00
..
add.c add: remove support for git-legacy-stash 2022-01-27 18:00:15 -08:00
am.c Merge branch 'ab/date-mode-release' 2022-02-25 15:47:36 -08:00
annotate.c
apply.c
archive.c
bisect--helper.c Merge branch 'ac/usage-string-fixups' 2022-03-06 21:25:32 -08:00
blame.c Merge branch 'ja/i18n-common-messages' 2022-02-25 15:47:35 -08:00
branch.c Merge branch 'gc/branch-recurse-submodules' 2022-02-18 13:53:29 -08:00
bugreport.c
bundle.c
cat-file.c cat-file: s/_/-/ in typo'd usage_msg_optf() message 2022-01-12 10:12:39 -08:00
check-attr.c
check-ignore.c
check-mailmap.c
check-ref-format.c
checkout--worker.c
checkout-index.c checkout-index: integrate with sparse index 2022-01-13 13:49:45 -08:00
checkout.c switch: mention the --detach option when dying due to lack of a branch 2022-02-25 22:21:48 -08:00
clean.c Merge branch 'vd/sparse-clean-etc' 2022-02-17 16:25:05 -08:00
clone.c Merge branch 'js/apply-partial-clone-filters-recursively' 2022-02-25 15:47:35 -08:00
column.c
commit-graph.c Merge branch 'ab/ignore-replace-while-working-on-commit-graph' 2021-11-01 13:48:08 -07:00
commit-tree.c
commit.c hooks: fix an obscure TOCTOU "did we just run a hook?" race 2022-03-07 13:00:53 -08:00
config.c
count-objects.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
credential-cache--daemon.c
credential-cache.c
credential-store.c
credential.c doc: fix git credential synopsis 2021-10-28 09:57:09 -07:00
describe.c i18n: turn even more messages into "cannot be used together" ones 2022-01-05 13:31:00 -08:00
diff-files.c
diff-index.c
diff-tree.c i18n: refactor "foo and bar are mutually exclusive" 2022-01-05 13:29:23 -08:00
diff.c builtin/diff.c: fix "git-diff" usage string typo 2022-02-02 11:30:53 -08:00
difftool.c i18n: factorize more 'incompatible options' messages 2022-02-04 13:58:28 -08:00
env--helper.c
fast-export.c i18n: fix some misformated placeholders in command synopsis 2022-02-04 13:58:28 -08:00
fast-import.c Merge branch 'ab/c99-designated-initializers' 2022-03-06 21:25:32 -08:00
fetch-pack.c
fetch.c Merge branch 'ja/i18n-common-messages' 2022-02-25 15:47:35 -08:00
fmt-merge-msg.c merge: allow to pretend a merge is made into a different branch 2021-12-20 14:55:02 -08:00
for-each-ref.c
for-each-repo.c
fsck.c run-command API users: use strvec_pushl(), not argv construction 2021-11-25 22:15:07 -08:00
gc.c Merge branch 'ab/config-based-hooks-2' 2022-02-09 14:21:00 -08:00
get-tar-commit-id.c
grep.c Merge branch 'ab/grep-patterntype' 2022-02-25 15:47:36 -08:00
hash-object.c Merge branch 'ja/i18n-common-messages' 2022-02-25 15:47:35 -08:00
help.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
hook.c git hook run: add an --ignore-missing flag 2022-01-07 15:19:34 -08:00
index-pack.c index-pack: clarify the breached limit 2022-02-23 17:41:10 -08:00
init-db.c i18n: refactor "foo and bar are mutually exclusive" 2022-01-05 13:29:23 -08:00
interpret-trailers.c
log.c Merge branch 'ab/grep-patterntype' 2022-02-25 15:47:36 -08:00
ls-files.c ls-files: support --recurse-submodules --stage 2022-02-23 16:41:55 -08:00
ls-remote.c ls-remote & transport API: release "struct transport_ls_refs_options" 2022-02-06 18:02:34 -08:00
ls-tree.c built-ins: trust the "prefix" from run_builtin() 2022-02-15 18:00:50 -08:00
mailinfo.c
mailsplit.c
merge-base.c i18n: factorize more 'incompatible options' messages 2022-02-04 13:58:28 -08:00
merge-file.c xdiff: implement a zealous diff3, or "zdiff3" 2021-12-01 14:45:58 -08:00
merge-index.c
merge-ours.c
merge-recursive.c
merge-tree.c
merge.c hooks: fix an obscure TOCTOU "did we just run a hook?" race 2022-03-07 13:00:53 -08:00
mktag.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
mktree.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
multi-pack-index.c builtin/multi-pack-index.c: don't leak concatenated options 2021-10-28 15:32:14 -07:00
mv.c
name-rev.c name-rev: replace --stdin with --annotate-stdin in synopsis 2022-02-15 17:37:43 -08:00
notes.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
pack-objects.c Merge branch 'ja/i18n-common-messages' 2022-02-25 15:47:35 -08:00
pack-redundant.c
pack-refs.c
patch-id.c patch-id: fix scan_hunk_header on diffs with 1 line of before/after 2022-02-02 11:24:23 -08:00
prune-packed.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
prune.c Merge branch 'ns/tmp-objdir' 2022-01-03 16:24:15 -08:00
pull.c Merge branch 'ja/i18n-common-messages' 2022-02-25 15:47:35 -08:00
push.c i18n: factorize "invalid value" messages 2022-02-04 13:58:28 -08:00
range-diff.c
read-tree.c
rebase.c Merge branch 'ja/i18n-common-messages' 2022-02-25 15:47:35 -08:00
receive-pack.c hooks: fix an obscure TOCTOU "did we just run a hook?" race 2022-03-07 13:00:53 -08:00
reflog.c Merge branch 'ac/usage-string-fixups' 2022-03-06 21:25:32 -08:00
remote-ext.c
remote-fd.c
remote.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
repack.c Merge branch 'ja/i18n-similar-messages' 2022-01-10 11:52:56 -08:00
replace.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
rerere.c
reset.c Merge branch 'ab/diff-free-more' 2022-02-25 15:47:36 -08:00
rev-list.c i18n: fix some misformated placeholders in command synopsis 2022-02-04 13:58:28 -08:00
rev-parse.c
revert.c
rm.c Merge branch 'ja/i18n-similar-messages' 2022-01-10 11:52:56 -08:00
send-pack.c i18n: factorize "invalid value" messages 2022-02-04 13:58:28 -08:00
shortlog.c log: add a --no-graph option 2022-02-11 10:06:41 -08:00
show-branch.c date API: create a date.h, split from cache.h 2022-02-16 09:40:00 -08:00
show-index.c
show-ref.c
sparse-checkout.c Merge branch 'en/sparse-checkout-fixes' 2022-03-06 21:25:30 -08:00
stash.c stash: strip "refs/heads/" with skip_prefix 2022-02-24 11:06:18 -08:00
stripspace.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
submodule--helper.c Merge branch 'ac/usage-string-fixups' 2022-03-06 21:25:32 -08:00
symbolic-ref.c
tag.c date API: create a date.h, split from cache.h 2022-02-16 09:40:00 -08:00
unpack-file.c
unpack-objects.c
update-index.c Merge branch 'vd/sparse-clean-etc' 2022-02-17 16:25:05 -08:00
update-ref.c
update-server-info.c i18n: remove from i18n strings that do not hold translatable parts 2022-02-04 13:58:28 -08:00
upload-archive.c upload-archive: use regular "struct child_process" pattern 2021-11-25 22:15:07 -08:00
upload-pack.c
var.c var: add GIT_DEFAULT_BRANCH variable 2021-11-03 13:25:36 -07:00
verify-commit.c
verify-pack.c
verify-tag.c
worktree.c Merge branch 'ds/worktree-docs' 2022-03-06 21:25:31 -08:00
write-tree.c