aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-01-21 08:44:53 -0800
committerJunio C Hamano <gitster@pobox.com>2025-01-21 08:44:53 -0800
commitcb441e1ec3f3cf475d9037a4ce74e8fccd6be7d8 (patch)
tree235fe13d72cc2897e498dbdd5d7a9ab0ad7c5415
parent57ebdd5af4031ddd0e012e68c5e423fd0671ed8c (diff)
parent0b4f8afef6b744d5aa92883c5a6c1985be67cc7c (diff)
downloadgit-cb441e1ec3f3cf475d9037a4ce74e8fccd6be7d8.tar.gz
Merge branch 'ps/reftable-get-random-fix'
The code to compute "unique" name used git_rand() which can fail or get stuck; the callsite does not require cryptographic security. Introduce the "insecure" mode and use it appropriately. * ps/reftable-get-random-fix: reftable/stack: accept insecure random bytes wrapper: allow generating insecure random bytes
-rw-r--r--builtin/gc.c2
-rw-r--r--reftable/stack.c4
-rw-r--r--t/helper/test-csprng.c2
-rw-r--r--t/unit-tests/t-reftable-readwrite.c6
-rw-r--r--wrapper.c24
-rw-r--r--wrapper.h16
6 files changed, 33 insertions, 21 deletions
diff --git a/builtin/gc.c b/builtin/gc.c
index a9b1c36de2..3e754f25bb 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1909,7 +1909,7 @@ static int get_random_minute(void)
if (getenv("GIT_TEST_MAINT_SCHEDULER"))
return 13;
- return git_rand() % 60;
+ return git_rand(0) % 60;
}
static int is_launchctl_available(void)
diff --git a/reftable/stack.c b/reftable/stack.c
index 531660a49f..572a74e00f 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -493,7 +493,7 @@ static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
close(fd);
fd = -1;
- delay = delay + (delay * rand()) / RAND_MAX + 1;
+ delay = delay + (delay * git_rand(CSPRNG_BYTES_INSECURE)) / UINT32_MAX + 1;
sleep_millisec(delay);
}
@@ -659,7 +659,7 @@ int reftable_stack_add(struct reftable_stack *st,
static int format_name(struct reftable_buf *dest, uint64_t min, uint64_t max)
{
char buf[100];
- uint32_t rnd = (uint32_t)git_rand();
+ uint32_t rnd = git_rand(CSPRNG_BYTES_INSECURE);
snprintf(buf, sizeof(buf), "0x%012" PRIx64 "-0x%012" PRIx64 "-%08x",
min, max, rnd);
reftable_buf_reset(dest);
diff --git a/t/helper/test-csprng.c b/t/helper/test-csprng.c
index a4a0aca617..c86dcc4870 100644
--- a/t/helper/test-csprng.c
+++ b/t/helper/test-csprng.c
@@ -15,7 +15,7 @@ int cmd__csprng(int argc, const char **argv)
while (count) {
unsigned long chunk = count < sizeof(buf) ? count : sizeof(buf);
- if (csprng_bytes(buf, chunk) < 0) {
+ if (csprng_bytes(buf, chunk, 0) < 0) {
perror("failed to read");
return 5;
}
diff --git a/t/unit-tests/t-reftable-readwrite.c b/t/unit-tests/t-reftable-readwrite.c
index 6b75a419b9..f22b977563 100644
--- a/t/unit-tests/t-reftable-readwrite.c
+++ b/t/unit-tests/t-reftable-readwrite.c
@@ -108,8 +108,8 @@ static void t_log_buffer_size(void)
hash, to ensure that the compressed part is larger than the original.
*/
for (i = 0; i < REFTABLE_HASH_SIZE_SHA1; i++) {
- log.value.update.old_hash[i] = (uint8_t)(git_rand() % 256);
- log.value.update.new_hash[i] = (uint8_t)(git_rand() % 256);
+ log.value.update.old_hash[i] = (uint8_t)(git_rand(0) % 256);
+ log.value.update.new_hash[i] = (uint8_t)(git_rand(0) % 256);
}
reftable_writer_set_limits(w, update_index, update_index);
err = reftable_writer_add_log(w, &log);
@@ -325,7 +325,7 @@ static void t_log_zlib_corruption(void)
};
for (i = 0; i < sizeof(message) - 1; i++)
- message[i] = (uint8_t)(git_rand() % 64 + ' ');
+ message[i] = (uint8_t)(git_rand(0) % 64 + ' ');
reftable_writer_set_limits(w, 1, 1);
diff --git a/wrapper.c b/wrapper.c
index fa79fd6ec9..8b98593149 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -479,7 +479,7 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)
for (count = 0; count < TMP_MAX; ++count) {
int i;
uint64_t v;
- if (csprng_bytes(&v, sizeof(v)) < 0)
+ if (csprng_bytes(&v, sizeof(v), 0) < 0)
return error_errno("unable to get random bytes for temporary file");
/* Fill in the random bits. */
@@ -750,7 +750,7 @@ int open_nofollow(const char *path, int flags)
#endif
}
-int csprng_bytes(void *buf, size_t len)
+int csprng_bytes(void *buf, size_t len, MAYBE_UNUSED unsigned flags)
{
#if defined(HAVE_ARC4RANDOM) || defined(HAVE_ARC4RANDOM_LIBBSD)
/* This function never returns an error. */
@@ -785,14 +785,18 @@ int csprng_bytes(void *buf, size_t len)
return -1;
return 0;
#elif defined(HAVE_OPENSSL_CSPRNG)
- int res = RAND_bytes(buf, len);
- if (res == 1)
+ switch (RAND_pseudo_bytes(buf, len)) {
+ case 1:
return 0;
- if (res == -1)
- errno = ENOTSUP;
- else
+ case 0:
+ if (flags & CSPRNG_BYTES_INSECURE)
+ return 0;
errno = EIO;
- return -1;
+ return -1;
+ default:
+ errno = ENOTSUP;
+ return -1;
+ }
#else
ssize_t res;
char *p = buf;
@@ -816,11 +820,11 @@ int csprng_bytes(void *buf, size_t len)
#endif
}
-uint32_t git_rand(void)
+uint32_t git_rand(unsigned flags)
{
uint32_t result;
- if (csprng_bytes(&result, sizeof(result)) < 0)
+ if (csprng_bytes(&result, sizeof(result), flags) < 0)
die(_("unable to get random bytes"));
return result;
diff --git a/wrapper.h b/wrapper.h
index a6b3e1f09e..7df824e34a 100644
--- a/wrapper.h
+++ b/wrapper.h
@@ -127,18 +127,26 @@ int open_nofollow(const char *path, int flags);
void sleep_millisec(int millisec);
+enum {
+ /*
+ * Accept insecure bytes, which some CSPRNG implementations may return
+ * in case the entropy pool has been exhausted.
+ */
+ CSPRNG_BYTES_INSECURE = (1 << 0),
+};
+
/*
* Generate len bytes from the system cryptographically secure PRNG.
* Returns 0 on success and -1 on error, setting errno. The inability to
- * satisfy the full request is an error.
+ * satisfy the full request is an error. Accepts CSPRNG flags.
*/
-int csprng_bytes(void *buf, size_t len);
+int csprng_bytes(void *buf, size_t len, unsigned flags);
/*
* Returns a random uint32_t, uniformly distributed across all possible
- * values.
+ * values. Accepts CSPRNG flags.
*/
-uint32_t git_rand(void);
+uint32_t git_rand(unsigned flags);
/* Provide log2 of the given `size_t`. */
static inline unsigned log2u(uintmax_t sz)