1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-04-28 16:55:09 +02:00

tempfile: avoid directory cleanup race

The temporary directory created by mks_tempfile_dt() is deleted by first
deleting the file within, then truncating the filename strbuf and
passing the resulting string to rmdir(2).  When the cleanup routine is
invoked concurrently by a signal handler we can end up passing the now
truncated string to unlink(2), however, which could cause problems on
some systems.

Avoid that issue by remembering the directory name separately.  This way
the paths stay unchanged.  A signal handler can still race with normal
cleanup, but deleting the same files and directories twice is harmless.

Reported-by: Jeff King <peff@peff.net>
Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
René Scharfe 2022-08-27 00:46:29 +02:00 committed by Junio C Hamano
parent 0f5bd024f2
commit babe2e0559
2 changed files with 7 additions and 9 deletions

View File

@ -59,14 +59,11 @@ static VOLATILE_LIST_HEAD(tempfile_list);
static void remove_template_directory(struct tempfile *tempfile,
int in_signal_handler)
{
if (tempfile->directorylen > 0 &&
tempfile->directorylen < tempfile->filename.len &&
tempfile->filename.buf[tempfile->directorylen] == '/') {
strbuf_setlen(&tempfile->filename, tempfile->directorylen);
if (tempfile->directory) {
if (in_signal_handler)
rmdir(tempfile->filename.buf);
rmdir(tempfile->directory);
else
rmdir_or_warn(tempfile->filename.buf);
rmdir_or_warn(tempfile->directory);
}
}
@ -115,7 +112,7 @@ static struct tempfile *new_tempfile(void)
tempfile->owner = 0;
INIT_LIST_HEAD(&tempfile->list);
strbuf_init(&tempfile->filename, 0);
tempfile->directorylen = 0;
tempfile->directory = NULL;
return tempfile;
}
@ -141,6 +138,7 @@ static void deactivate_tempfile(struct tempfile *tempfile)
{
tempfile->active = 0;
strbuf_release(&tempfile->filename);
free(tempfile->directory);
volatile_list_del(&tempfile->list);
free(tempfile);
}
@ -254,7 +252,7 @@ struct tempfile *mks_tempfile_dt(const char *directory_template,
tempfile = new_tempfile();
strbuf_swap(&tempfile->filename, &sb);
tempfile->directorylen = directorylen;
tempfile->directory = xmemdupz(tempfile->filename.buf, directorylen);
tempfile->fd = fd;
activate_tempfile(tempfile);
return tempfile;

View File

@ -82,7 +82,7 @@ struct tempfile {
FILE *volatile fp;
volatile pid_t owner;
struct strbuf filename;
size_t directorylen;
char *directory;
};
/*