浏览代码

major improvements to temp file name generator

use current time in nanoseconds and some potentially-random (if aslr
is enabled) pointer values for the initial tempfile name generation,
and step via a cheap linear prng on collisions. limit the number of
retry attempts to prevent denial of service attacks even if an
attacker can guess the filenames.
Rich Felker 14 年之前
父节点
当前提交
446b4207cc
共有 3 个文件被更改,包括 21 次插入16 次删除
  1. 3 1
      src/temp/mkdtemp.c
  2. 3 2
      src/temp/mkstemp.c
  3. 15 13
      src/temp/mktemp.c

+ 3 - 1
src/temp/mkdtemp.c

@@ -12,7 +12,8 @@ char *__mktemp(char *);
 
 char *mkdtemp(char *template)
 {
-	for (;;) {
+	int retries = 100;
+	while (retries--) {
 		if (!__mktemp(template)) return 0;
 		if (!mkdir(template, 0700)) return template;
 		if (errno != EEXIST) return 0;
@@ -20,4 +21,5 @@ char *mkdtemp(char *template)
 		 * that we have a valid template string */
 		strcpy(template+strlen(template)-6, "XXXXXX");
 	}
+	return 0;
 }

+ 3 - 2
src/temp/mkstemp.c

@@ -11,8 +11,8 @@ char *__mktemp(char *);
 
 int mkstemp(char *template)
 {
-	int fd;
-	for (;;) {
+	int fd, retries = 100;
+	while (retries--) {
 		if (!__mktemp(template)) return 0;
 		if ((fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600))>=0)
 			return fd;
@@ -21,6 +21,7 @@ int mkstemp(char *template)
 		 * that we have a valid template string */
 		strcpy(template+strlen(template)-6, "XXXXXX");
 	}
+	return -1;
 }
 
 LFS64(mkstemp);

+ 15 - 13
src/temp/mktemp.c

@@ -4,28 +4,30 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
+#include <time.h>
+#include <stdint.h>
 #include "libc.h"
 
 char *__mktemp(char *template)
 {
-	static int lock;
-	static int index;
-	int l = strlen(template);
+	struct timespec ts;
+	size_t l = strlen(template);
+	int retries = 10000;
+	unsigned long r;
 
 	if (l < 6 || strcmp(template+l-6, "XXXXXX")) {
 		errno = EINVAL;
-		return NULL;
+		return 0;
 	}
-	LOCK(&lock);
-	for (; index < 1000000; index++) {
-		snprintf(template+l-6, 6, "%06d", index);
-		if (access(template, F_OK) != 0) {
-			UNLOCK(&lock);
-			return template;
-		}
+	clock_gettime(CLOCK_REALTIME, &ts);
+	r = ts.tv_nsec + (uintptr_t)&ts / 16 + (uintptr_t)template;
+	while (retries--) {
+		snprintf(template+l-6, 7, "%06lX", r & 0xffffff);
+		if (access(template, F_OK) < 0) return template;
+		r = r * 1103515245 + 12345;
 	}
-	UNLOCK(&lock);
-	return NULL;	
+	errno = EEXIST;
+	return 0;
 }
 
 weak_alias(__mktemp, mktemp);