mbox series

[v2,0/1] maintenance: Fix SEGFAULT when running outside of a repository

Message ID 20201126204141.1438-1-rafaeloliveira.cs@gmail.com (mailing list archive)
Headers show
Series maintenance: Fix SEGFAULT when running outside of a repository | expand

Message

Rafael Silva Nov. 26, 2020, 8:41 p.m. UTC
In d7514f6ed5 (maintenance: take a lock on the objects directory, 2020-09-17) [1],
and 2fec604f8d (maintenance: add start/stop subcommands, 2020-09-11) [2] The
"git maintenance run" and "git maintenance start" was taught to hold a file-based
lock at the .git/maintenance.lock and .git/schedule.lock respectively because these
operations involves writing data into the .git/repository. 

The lock file path string is built using the the_repository->objects->odb->path,
in case the_repository->objects->odb is NULL when there is not repository available,
resulting in a SEGFAULT.

In order to reproduce the error, one can execute maintenance "run" and/or
"start" subcommand with a non valid repository: 

    $ git -C /tmp maintenance start
    Segmentation fault

    $ git -C /tmp maintenance run
    Segmentation fault

The above test was executed from a git built from commit: faefdd61ec (Sixth batch, 2020-11-18):

For reference here's the output from GDB when debugging the "start" command

	Program received signal SIGSEGV, Segmentation fault.
	0x00005555555b9b4c in maintenance_run_tasks (opts=0x7fffffffded4) at builtin/gc.c:1268
	1268		char *lock_path = xstrfmt("%s/maintenance", r->objects->odb->path);


Updates in v2
=============

  * Instead of implementing the check on the subcommands, a more robust approach
    is taken by replacing the "maintenance" command option to use RUN_SETUP
    instead of RUN_SETUP_GENTLY as suggested by Derrick Stolee in [3] as part of
    review cycle from v1.

    This provides protection for all maintenance subcommands given that
    currently all the commands are required to be executed inside a repository.

  * As the RUN_SETUP will enable protection to all commands, the checks in
    maintenance_register() and maintenance_unregister() are removed as they
    are not required anymore.

  * Use the "nongit" helper function for testing it instead of relying on the
    `/tmp` directory for a non valid git repository as suggested by
    SZEDER Gábor and Eric Sunshine in [4].

  * All "git maintenance" subcommands are included on the test to ensure the
   behaviour is consistent for all subcommands. In particular the "register"
   command that current exists without a message and code 0 which will be
   changed by this patch to fail when running outside of a repository. 

   It also worth noting that "register" command does not exists in a released
   version of Git as mentioned in [5] which make it easier for changing the
   current behaviour of the command

[1] https://lore.kernel.org/git/1a0a3eebb825ac3eabfdd86f82ed7ef6abb454c5.1600366313.git.gitgitgadget@gmail.com/
[2] https://lore.kernel.org/git/5194f6b1facbd14cc17eea0337c0cc397a2a51fc.1602782524.git.gitgitgadget@gmail.com/
[3] https://lore.kernel.org/git/1bfd84da-5b74-be10-fc2c-dee80111ee2d@gmail.com/
[4] https://lore.kernel.org/git/20201124191407.GC8396@szeder.dev/
[5] https://lore.kernel.org/git/54fa678c-7150-8c48-50e5-b33923a69249@gmail.com/

Thanks everyone for the insightful and helpful feedback.

Rafael Silva (1):
  maintenance: fix SEGFAULT when no repository

 builtin/gc.c           | 7 -------
 git.c                  | 2 +-
 t/t7900-maintenance.sh | 8 ++++++++
 3 files changed, 9 insertions(+), 8 deletions(-)