[klibc] [PATCH] Add minimal mkstemp(3) implementation.

maximilian attems max at stro.at
Tue Jun 28 08:54:54 PDT 2011


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 klibc
useless 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.1

I didn't test it yet. could you resubmit with aboves fixed?

-- 
maks



More information about the klibc mailing list