Skip to content

Commit 4467bd6

Browse files
authored
Merge pull request libgit2#6207 from libgit2/ethomson/prng
mktmp: improve our temp file creation
2 parents 1d811f0 + b933c14 commit 4467bd6

File tree

15 files changed

+344
-48
lines changed

15 files changed

+344
-48
lines changed

COPYING

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,3 +1132,15 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
11321132
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
11331133
OF THE POSSIBILITY OF SUCH DAMAGE.
11341134

1135+
----------------------------------------------------------------------
1136+
1137+
The xoroshiro256** implementation is licensed in the public domain:
1138+
1139+
Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
1140+
1141+
To the extent possible under law, the author has dedicated all copyright
1142+
and related and neighboring rights to this software to the public domain
1143+
worldwide. This software is distributed without any warranty.
1144+
1145+
See <http://creativecommons.org/publicdomain/zero/1.0/>.
1146+

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ check_prototype_definition(qsort_r
5555

5656
check_function_exists(qsort_s GIT_QSORT_S)
5757

58+
check_function_exists(getentropy GIT_RAND_GETENTROPY)
59+
5860
# Find required dependencies
5961

6062
if(WIN32)

src/features.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@
4848
#cmakedefine GIT_SHA1_OPENSSL 1
4949
#cmakedefine GIT_SHA1_MBEDTLS 1
5050

51+
#cmakedefine GIT_RAND_GETENTROPY 1
52+
5153
#endif

src/fs_path.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,8 +1040,8 @@ int git_fs_path_iconv(git_fs_path_iconv_t *ic, const char **in, size_t *inlen)
10401040
return -1;
10411041
}
10421042

1043-
static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D.XXXXXX";
1044-
static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D.XXXXXX";
1043+
static const char *nfc_file = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D";
1044+
static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D";
10451045

10461046
/* Check if the platform is decomposing unicode data for us. We will
10471047
* emulate core Git and prefer to use precomposed unicode data internally
@@ -1054,39 +1054,42 @@ static const char *nfd_file = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D.XXXXXX";
10541054
*/
10551055
bool git_fs_path_does_decompose_unicode(const char *root)
10561056
{
1057-
git_str path = GIT_STR_INIT;
1057+
git_str nfc_path = GIT_STR_INIT;
1058+
git_str nfd_path = GIT_STR_INIT;
10581059
int fd;
10591060
bool found_decomposed = false;
1060-
char tmp[6];
1061+
size_t orig_len;
1062+
const char *trailer;
10611063

10621064
/* Create a file using a precomposed path and then try to find it
10631065
* using the decomposed name. If the lookup fails, then we will mark
10641066
* that we should precompose unicode for this repository.
10651067
*/
1066-
if (git_str_joinpath(&path, root, nfc_file) < 0 ||
1067-
(fd = p_mkstemp(path.ptr)) < 0)
1068+
if (git_str_joinpath(&nfc_path, root, nfc_file) < 0)
1069+
goto done;
1070+
1071+
/* record original path length before trailer */
1072+
orig_len = nfc_path.size;
1073+
1074+
if ((fd = git_futils_mktmp(&nfc_path, nfc_path.ptr, 0666)) < 0)
10681075
goto done;
10691076
p_close(fd);
10701077

1071-
/* record trailing digits generated by mkstemp */
1072-
memcpy(tmp, path.ptr + path.size - sizeof(tmp), sizeof(tmp));
1078+
trailer = nfc_path.ptr + orig_len;
10731079

10741080
/* try to look up as NFD path */
1075-
if (git_str_joinpath(&path, root, nfd_file) < 0)
1081+
if (git_str_joinpath(&nfd_path, root, nfd_file) < 0 ||
1082+
git_str_puts(&nfd_path, trailer) < 0)
10761083
goto done;
1077-
memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp));
10781084

1079-
found_decomposed = git_fs_path_exists(path.ptr);
1085+
found_decomposed = git_fs_path_exists(nfd_path.ptr);
10801086

10811087
/* remove temporary file (using original precomposed path) */
1082-
if (git_str_joinpath(&path, root, nfc_file) < 0)
1083-
goto done;
1084-
memcpy(path.ptr + path.size - sizeof(tmp), tmp, sizeof(tmp));
1085-
1086-
(void)p_unlink(path.ptr);
1088+
(void)p_unlink(nfc_path.ptr);
10871089

10881090
done:
1089-
git_str_dispose(&path);
1091+
git_str_dispose(&nfc_path);
1092+
git_str_dispose(&nfd_path);
10901093
return found_decomposed;
10911094
}
10921095

src/futils.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "runtime.h"
1111
#include "strmap.h"
1212
#include "hash.h"
13+
#include "rand.h"
14+
1315
#include <ctype.h>
1416
#if GIT_WIN32
1517
#include "win32/findfile.h"
@@ -27,23 +29,20 @@ int git_futils_mkpath2file(const char *file_path, const mode_t mode)
2729
int git_futils_mktmp(git_str *path_out, const char *filename, mode_t mode)
2830
{
2931
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;
32+
unsigned int tries = 32;
3233
int fd;
3334

3435
while (tries--) {
36+
uint64_t rand = git_rand_next();
37+
3538
git_str_sets(path_out, filename);
36-
git_str_puts(path_out, "_git2_XXXXXX");
39+
git_str_puts(path_out, "_git2_");
40+
git_str_encode_hexstr(path_out, (void *)&rand, sizeof(uint64_t));
3741

3842
if (git_str_oom(path_out))
3943
return -1;
4044

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;
46-
45+
/* Note that we open with O_CREAT | O_EXCL */
4746
if ((fd = p_open(path_out->ptr, open_flags, mode)) >= 0)
4847
return fd;
4948
}

src/futils.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,12 @@ extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags
177177
* protected directory; the file created will created will honor
178178
* the current `umask`. Writes the filename into path_out.
179179
*
180-
* This function is *NOT* suitable for use in temporary directories
181-
* that are world writable. It uses `mktemp` (for portability) and
182-
* many `mktemp` implementations use weak random characters. It
183-
* should only be assumed to be suitable for atomically writing
184-
* a new file in a directory that you control.
180+
* This function uses a high-quality PRNG seeded by the system's
181+
* entropy pool _where available_ and falls back to a simple seed
182+
* (time plus system information) when not. This is suitable for
183+
* writing within a protected directory, but the system's safe
184+
* temporary file creation functions should be preferred where
185+
* available when writing into world-writable (temp) directories.
185186
*
186187
* @return On success, an open file descriptor, else an error code < 0.
187188
*/

src/libgit2.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "mwindow.h"
2121
#include "object.h"
2222
#include "odb.h"
23+
#include "rand.h"
2324
#include "refs.h"
2425
#include "runtime.h"
2526
#include "sysdir.h"
@@ -70,6 +71,7 @@ int git_libgit2_init(void)
7071
git_allocator_global_init,
7172
git_threadstate_global_init,
7273
git_threads_global_init,
74+
git_rand_global_init,
7375
git_hash_global_init,
7476
git_sysdir_global_init,
7577
git_filter_global_init,

src/posix.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ extern ssize_t p_pwrite(int fd, const void *data, size_t size, off64_t offset);
131131

132132
#define p_close(fd) close(fd)
133133
#define p_umask(m) umask(m)
134-
#define p_mktemp(p) mktemp(p)
135134

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

0 commit comments

Comments
 (0)