Procházet zdrojové kódy

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 před 14 roky
rodič
revize
446b4207cc
3 změnil soubory, kde provedl 21 přidání a 16 odebrání
  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)
 char *mkdtemp(char *template)
 {
 {
-	for (;;) {
+	int retries = 100;
+	while (retries--) {
 		if (!__mktemp(template)) return 0;
 		if (!__mktemp(template)) return 0;
 		if (!mkdir(template, 0700)) return template;
 		if (!mkdir(template, 0700)) return template;
 		if (errno != EEXIST) return 0;
 		if (errno != EEXIST) return 0;
@@ -20,4 +21,5 @@ char *mkdtemp(char *template)
 		 * that we have a valid template string */
 		 * that we have a valid template string */
 		strcpy(template+strlen(template)-6, "XXXXXX");
 		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 mkstemp(char *template)
 {
 {
-	int fd;
-	for (;;) {
+	int fd, retries = 100;
+	while (retries--) {
 		if (!__mktemp(template)) return 0;
 		if (!__mktemp(template)) return 0;
 		if ((fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600))>=0)
 		if ((fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600))>=0)
 			return fd;
 			return fd;
@@ -21,6 +21,7 @@ int mkstemp(char *template)
 		 * that we have a valid template string */
 		 * that we have a valid template string */
 		strcpy(template+strlen(template)-6, "XXXXXX");
 		strcpy(template+strlen(template)-6, "XXXXXX");
 	}
 	}
+	return -1;
 }
 }
 
 
 LFS64(mkstemp);
 LFS64(mkstemp);

+ 15 - 13
src/temp/mktemp.c

@@ -4,28 +4,30 @@
 #include <fcntl.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <errno.h>
 #include <errno.h>
+#include <time.h>
+#include <stdint.h>
 #include "libc.h"
 #include "libc.h"
 
 
 char *__mktemp(char *template)
 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")) {
 	if (l < 6 || strcmp(template+l-6, "XXXXXX")) {
 		errno = EINVAL;
 		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);
 weak_alias(__mktemp, mktemp);