[klibc] [PATCH] Add minimal mkstemp(3) implementation.
Thorsten Glaser
tg at mirbsd.org
Sun Feb 27 12:35:29 PST 2011
This uses time, ASLR and pid for randomisation. (Closes: #516774)
Signed-off-by: Thorsten Glaser <tg at mirbsd.org>
---
usr/include/stdlib.h | 2 +
usr/klibc/Kbuild | 2 +-
usr/klibc/mkstemp.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 96 insertions(+), 1 deletions(-)
create mode 100644 usr/klibc/mkstemp.c
diff --git a/usr/include/stdlib.h b/usr/include/stdlib.h
index 406f446..4706f71 100644
--- a/usr/include/stdlib.h
+++ b/usr/include/stdlib.h
@@ -79,6 +79,8 @@ static __inline__ void srandom(unsigned int __s)
srand48(__s);
}
+__extern int mkstemp(char *);
+
/* Basic PTY functions. These only work if devpts is mounted! */
__extern int unlockpt(int);
diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
index af40367..62a3268 100644
--- a/usr/klibc/Kbuild
+++ b/usr/klibc/Kbuild
@@ -18,7 +18,7 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \
setpgrp.o getpgrp.o daemon.o \
printf.o vprintf.o fprintf.o vfprintf.o perror.o \
statfs.o fstatfs.o umount.o \
- creat.o open.o openat.o open_cloexec.o \
+ creat.o mkstemp.o open.o openat.o open_cloexec.o \
fopen.o fread.o fread2.o fgetc.o fgets.o \
fwrite.o fwrite2.o fputc.o fputs.o puts.o putchar.o \
sleep.o usleep.o strtotimespec.o strtotimeval.o \
diff --git a/usr/klibc/mkstemp.c b/usr/klibc/mkstemp.c
new file mode 100644
index 0000000..8430357
--- /dev/null
+++ b/usr/klibc/mkstemp.c
@@ -0,0 +1,93 @@
+/*-
+ * Compact mkstemp(3)-only implementation, for klibc
+ *
+ * Copyright (c) 2009, 2011
+ * Thorsten Glaser <tg at mirbsd.de>
+ *
+ * This file is available under the same terms ("historic
+ * permission clause") as klibc itself or under the terms
+ * of The MirOS Licence (dual licenced).
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+mkstemp(char *template)
+{
+ int i;
+ char *cp, *sp;
+ union {
+ unsigned short seed[3]; /* for jrand48 */
+ uint64_t stuffing; /* for seeding */
+ } u;
+ struct stat sbuf;
+ struct timeval tv;
+
+ /* time ensures basic distribution */
+ gettimeofday(&tv, NULL);
+ u.stuffing = tv.tv_sec;
+ u.stuffing *= 1000000;
+ /* stack is randomised on all Linux platforms */
+ u.stuffing ^= (uint64_t)(ptrdiff_t)&i;
+ /* more time */
+ u.stuffing += tv.tv_usec;
+ /* pid ensures this differs after fork() */
+ u.stuffing ^= (uint64_t)getpid();
+
+ cp = template;
+ while (*cp)
+ ++cp;
+
+ sp = cp;
+ /* generate random suffix */
+ while (sp > template && sp[-1] == 'X') {
+ i = (int)((unsigned int)jrand48(u.seed) % (26 + 26));
+ *--sp = i < 26 ? 'A' + i : 'a' + i - 26;
+ }
+ if (sp == cp) {
+ /* zero-length template or no X at its end */
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* check the target directory */
+ cp = sp;
+ while (cp > template && *cp != '/')
+ --cp;
+ if (cp > template) {
+ *cp = '\0';
+ i = stat(template, &sbuf);
+ *cp = '/';
+
+ if (i != 0)
+ /* stat failed, pass errno */
+ return (-1);
+ if (!S_ISDIR(sbuf.st_mode)) {
+ errno = ENOTDIR;
+ return (-1);
+ }
+ }
+
+ while (1) {
+ if ((i = open(template, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0 ||
+ errno != EEXIST)
+ break;
+
+ while (*cp == 'Z')
+ if (!*++cp)
+ return (-1);
+ if (*cp == 'z')
+ *cp = 'A';
+ else
+ ++*cp;
+ }
+ return (i);
+}
--
1.6.3.1
More information about the klibc
mailing list