[PATCH] erofs-utils: lib: s3: fix SigV4 signature timestamp mismatch

Yifan Zhao zhaoyifan28 at huawei.com
Wed Jan 14 18:38:08 AEDT 2026


The current SigV4 implementation calls `s3erofs_now()` multiple times
during the signing process. This can cause inconsistent timestamps if a
second boundary is crossed, leading to signature verification failure.

Fix this by generating the timestamp once and passing it throughout the
signing process to ensure consistency.

Signed-off-by: Yifan Zhao <zhaoyifan28 at huawei.com>
---
 lib/remotes/s3.c | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/lib/remotes/s3.c b/lib/remotes/s3.c
index 223c3e8..97f06b4 100644
--- a/lib/remotes/s3.c
+++ b/lib/remotes/s3.c
@@ -315,11 +315,10 @@ enum s3erofs_date_format {
 	S3EROFS_DATE_YYYYMMDD
 };
 
-static void s3erofs_now(char *buf, size_t maxlen, enum s3erofs_date_format fmt)
+static void s3erofs_format_time(time_t t, char *buf, size_t maxlen, enum s3erofs_date_format fmt)
 {
 	const char *format;
-	time_t now = time(NULL);
-	struct tm *ptm = gmtime(&now);
+	struct tm *ptm = gmtime(&t);
 
 	switch (fmt) {
 	case S3EROFS_DATE_RFC1123:
@@ -402,10 +401,9 @@ free_string:
 
 // See: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
 static char *s3erofs_sigv4_header(const struct curl_slist *headers,
-				  const char *canonical_uri,
-				  const char *canonical_query,
-				  const char *region, const char *ak,
-				  const char *sk)
+				  time_t request_time, const char *canonical_uri,
+				  const char *canonical_query, const char *region,
+				  const char *ak, const char *sk)
 {
 	u8 ping_buf[EVP_MAX_MD_SIZE], pong_buf[EVP_MAX_MD_SIZE];
 	char hex_buf[EVP_MAX_MD_SIZE * 2 + 1];
@@ -423,10 +421,12 @@ static char *s3erofs_sigv4_header(const struct curl_slist *headers,
 		canonical_query = "";
 
 	canonical_headers = get_canonical_headers(headers);
+	if (!canonical_headers)
+		return ERR_PTR(-ENOMEM);
 
 	// Get current time in required formats
-	s3erofs_now(date_str, sizeof(date_str), S3EROFS_DATE_YYYYMMDD);
-	s3erofs_now(timestamp, sizeof(timestamp), S3EROFS_DATE_ISO8601);
+	s3erofs_format_time(request_time, date_str, sizeof(date_str), S3EROFS_DATE_YYYYMMDD);
+	s3erofs_format_time(request_time, timestamp, sizeof(timestamp), S3EROFS_DATE_ISO8601);
 
 	// Task 1: Create canonical request
 	if (asprintf(&canonical_request,
@@ -530,9 +530,8 @@ static int s3erofs_request_insert_auth_v2(struct curl_slist **request_headers,
 	char date[64], *sigv2;
 
 	memcpy(date, date_prefix, sizeof(date_prefix) - 1);
-	s3erofs_now(date + sizeof(date_prefix) - 1,
-		    sizeof(date) - sizeof(date_prefix) + 1,
-		    S3EROFS_DATE_RFC1123);
+	s3erofs_format_time(time(NULL), date + sizeof(date_prefix) - 1,
+			    sizeof(date) - sizeof(date_prefix) + 1, S3EROFS_DATE_RFC1123);
 
 	sigv2 = s3erofs_sigv2_header(*request_headers, NULL, NULL,
 				     date + sizeof(date_prefix) - 1, req->canonical_uri,
@@ -553,6 +552,7 @@ static int s3erofs_request_insert_auth_v4(struct curl_slist **request_headers,
 {
 	char timestamp[32], *sigv4, *tmp;
 	const char *host, *host_end;
+	time_t request_time = time(NULL);
 
 	/* Add following headers for SigV4 in alphabetical order: */
 	/* 1. host */
@@ -570,15 +570,15 @@ static int s3erofs_request_insert_auth_v4(struct curl_slist **request_headers,
 		*request_headers, "x-amz-content-sha256:UNSIGNED-PAYLOAD");
 
 	/* 3. x-amz-date */
-	s3erofs_now(timestamp, sizeof(timestamp), S3EROFS_DATE_ISO8601);
+	s3erofs_format_time(request_time, timestamp, sizeof(timestamp), S3EROFS_DATE_ISO8601);
 	if (asprintf(&tmp, "x-amz-date:%s", timestamp) < 0)
 		return -ENOMEM;
 	*request_headers = curl_slist_append(*request_headers, tmp);
 	free(tmp);
 
-	sigv4 = s3erofs_sigv4_header(*request_headers, req->canonical_uri,
-				     req->canonical_query, s3->region, s3->access_key,
-				     s3->secret_key);
+	sigv4 = s3erofs_sigv4_header(*request_headers, request_time,
+				     req->canonical_uri, req->canonical_query,
+				     s3->region, s3->access_key, s3->secret_key);
 	if (IS_ERR(sigv4))
 		return PTR_ERR(sigv4);
 	*request_headers = curl_slist_append(*request_headers, sigv4);
-- 
2.47.3



More information about the Linux-erofs mailing list