Skip to content

Commit babe2e0

Browse files
rscharfegitster
authored andcommitted
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 <[email protected]> Signed-off-by: René Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0f5bd02 commit babe2e0

File tree

2 files changed

+7
-9
lines changed

2 files changed

+7
-9
lines changed

tempfile.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,11 @@ static VOLATILE_LIST_HEAD(tempfile_list);
5959
static void remove_template_directory(struct tempfile *tempfile,
6060
int in_signal_handler)
6161
{
62-
if (tempfile->directorylen > 0 &&
63-
tempfile->directorylen < tempfile->filename.len &&
64-
tempfile->filename.buf[tempfile->directorylen] == '/') {
65-
strbuf_setlen(&tempfile->filename, tempfile->directorylen);
62+
if (tempfile->directory) {
6663
if (in_signal_handler)
67-
rmdir(tempfile->filename.buf);
64+
rmdir(tempfile->directory);
6865
else
69-
rmdir_or_warn(tempfile->filename.buf);
66+
rmdir_or_warn(tempfile->directory);
7067
}
7168
}
7269

@@ -115,7 +112,7 @@ static struct tempfile *new_tempfile(void)
115112
tempfile->owner = 0;
116113
INIT_LIST_HEAD(&tempfile->list);
117114
strbuf_init(&tempfile->filename, 0);
118-
tempfile->directorylen = 0;
115+
tempfile->directory = NULL;
119116
return tempfile;
120117
}
121118

@@ -141,6 +138,7 @@ static void deactivate_tempfile(struct tempfile *tempfile)
141138
{
142139
tempfile->active = 0;
143140
strbuf_release(&tempfile->filename);
141+
free(tempfile->directory);
144142
volatile_list_del(&tempfile->list);
145143
free(tempfile);
146144
}
@@ -254,7 +252,7 @@ struct tempfile *mks_tempfile_dt(const char *directory_template,
254252

255253
tempfile = new_tempfile();
256254
strbuf_swap(&tempfile->filename, &sb);
257-
tempfile->directorylen = directorylen;
255+
tempfile->directory = xmemdupz(tempfile->filename.buf, directorylen);
258256
tempfile->fd = fd;
259257
activate_tempfile(tempfile);
260258
return tempfile;

tempfile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ struct tempfile {
8282
FILE *volatile fp;
8383
volatile pid_t owner;
8484
struct strbuf filename;
85-
size_t directorylen;
85+
char *directory;
8686
};
8787

8888
/*

0 commit comments

Comments
 (0)