Skip to content

Commit 4ac5972

Browse files
committed
futils_mktmp: don't use umask.
Previously, we were using `umask(mask = umask(0))` to fetch the current umask in order to apply it to the desired mode, but this is broken in the presence of threads. There is no portable way to directly fetch umask without mutating it. Instead, add a reimplementation of mkstemp that uses a passed-in mode, instead of explicitly chmodding to 0600 like POSIX requires of mkstemp. Fixes: jmgao/pore#46
1 parent 8d54822 commit 4ac5972

File tree

2 files changed

+21
-17
lines changed

2 files changed

+21
-17
lines changed

src/futils.c

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,32 @@ int git_futils_mkpath2file(const char *file_path, const mode_t mode)
2626

2727
int git_futils_mktmp(git_str *path_out, const char *filename, mode_t mode)
2828
{
29+
const int open_flags = O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC;
30+
/* TMP_MAX is unrelated to mktemp but should provide a reasonable amount */
31+
unsigned int tries = TMP_MAX;
2932
int fd;
30-
mode_t mask;
3133

32-
p_umask(mask = p_umask(0));
34+
while (tries--) {
35+
git_str_sets(path_out, filename);
36+
git_str_puts(path_out, "_git2_XXXXXX");
3337

34-
git_str_sets(path_out, filename);
35-
git_str_puts(path_out, "_git2_XXXXXX");
36-
37-
if (git_str_oom(path_out))
38-
return -1;
38+
if (git_str_oom(path_out))
39+
return -1;
3940

40-
if ((fd = p_mkstemp(path_out->ptr)) < 0) {
41-
git_error_set(GIT_ERROR_OS,
42-
"failed to create temporary file '%s'", path_out->ptr);
43-
return -1;
44-
}
41+
/* Using mktemp is safe when we open with O_CREAT | O_EXCL */
42+
p_mktemp(path_out->ptr);
43+
/* mktemp sets template to empty string on failure */
44+
if (path_out->ptr[0] == '\0')
45+
break;
4546

46-
if (p_chmod(path_out->ptr, (mode & ~mask))) {
47-
git_error_set(GIT_ERROR_OS,
48-
"failed to set permissions on file '%s'", path_out->ptr);
49-
return -1;
47+
if ((fd = p_open(path_out->ptr, open_flags, mode)) >= 0)
48+
return fd;
5049
}
5150

52-
return fd;
51+
git_error_set(GIT_ERROR_OS,
52+
"failed to create temporary file '%s'", path_out->ptr);
53+
git_str_dispose(path_out);
54+
return -1;
5355
}
5456

5557
int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode)

src/posix.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "common.h"
1111

12+
#include <stdlib.h>
1213
#include <fcntl.h>
1314
#include <time.h>
1415

@@ -130,6 +131,7 @@ extern ssize_t p_pwrite(int fd, const void *data, size_t size, off64_t offset);
130131

131132
#define p_close(fd) close(fd)
132133
#define p_umask(m) umask(m)
134+
#define p_mktemp(p) mktemp(p)
133135

134136
extern int p_open(const char *path, int flags, ...);
135137
extern int p_creat(const char *path, mode_t mode);

0 commit comments

Comments
 (0)