Thorsten Glaser
2011-Feb-27 20:35 UTC
[klibc] [PATCH] Add minimal mkstemp(3) implementation.
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
Thorsten Glaser
2011-Feb-27 20:57 UTC
[klibc] [PATCH] Add minimal mkstemp(3) implementation.
Dixi quod?>This uses time, ASLR and pid for randomisation. (Closes: #516774)This patch replaces both the following ones I sent in January: ? <Pine.BSM.4.64L.1101291726340.10936.p1 at herc.mirbsd.org> ? <Pine.BSM.4.64L.1101291726340.10936.p2 at herc.mirbsd.org> This time I use jrand48(3) directly with very minimal seeding. I have put this patch, on top of today?s master (except the one changing the version number), plus my m68k patch from January ? <Pine.BSM.4.64L.1101291722390.10936 at herc.mirbsd.org> was that, in a Debian package, built it, installed it in a cowbuilder shell (throw-away sid chroot), built mksh against it (both statically and dynamically), and it passed the test suite with 0 unexpected failures, each. (Probably due to the open() fix; apparently the signal failures I saw were from the stack corruption.) I?ll now test it on m68k as well, to validate that patch. bye, //mirabilos -- 13:47?<tobiasu> if i were omnipotent, i would divide by zero all day long ;) (thinking about http://lobacevski.tumblr.com/post/3260866481 by waga)
Thorsten Glaser
2011-Jun-16 14:46 UTC
[klibc] [PATCH] Add minimal mkstemp(3) implementation.
Dixi quod?>>This uses time, ASLR and pid for randomisation. (Closes: #516774) > >This patch replaces both the following ones I sent in January:Ref: http://www.zytor.com/pipermail/klibc/2011-February/002854.html I built that with 1.5.22-1 on amd64, and mksh?s testsuite reports no errors, so I suppose this _may_ work on _some_ platforms now. (Thanks mrud for prodding.) bye, //mirabilos -- 22:59?<Vutral> glaub ich termkit is kompliziert | glabe nicht das man damit schneller arbeitet | reiz?berflutung ? wie windows ? alles evil zuviel bilder ? wie ein spiel | 23:00?<Vutral> die meisten raffen auch nicht mehr von windows | 23:01?<Vutral> bilderb?cher sind ja auch nich wirklich verbreitet als erwachsenen literatur ? who needs GUIs thus?
maximilian attems
2011-Jun-28 15:54 UTC
[klibc] [PATCH] Add minimal mkstemp(3) implementation.
sorry this sems to have gone unreviewed, here a first quick go. On Sun, 27 Feb 2011, Thorsten Glaser wrote:> This uses time, ASLR and pid for randomisation. (Closes: #516774)why do we want mkstemp(3), please add the motiviation directly in the patch body.> 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 \belongs more to stdlib.h stuff after env, getenv() and friends.> 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 klibcuseless info once merged.> + * > + * 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). > + */please no new license, could it stay just under first?> + > +#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);useless braces, happens at several return places..> + } > + > + /* 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)please put the '||` not at the line ending, but at the start of the next logical block.> + break; > + > + while (*cp == 'Z') > + if (!*++cp) > + return (-1);this block I don't understand too, what's up with 'Z'?> + if (*cp == 'z') > + *cp = 'A'; > + else > + ++*cp;this could use a comment too.> + } > + return (i);useless braces..> +} > -- > 1.6.3.1I didn't test it yet. could you resubmit with aboves fixed? -- maks