Thorsten Glaser
2012-Jan-28 21:15 UTC
[klibc] [PATCH] add mkstemp(3) using entropy from ELF aux vector AT_RANDOM
- update AT_* definitions - parse AT_RANDOM; provide some bytes as __klibc_rand48 - add mkstemp Signed-off-by: Thorsten Glaser <tg at mirbsd.org> --- usr/include/stdlib.h | 2 + usr/include/sys/elfcommon.h | 16 ++++++++- usr/klibc/Kbuild | 1 + usr/klibc/libc_init.c | 7 ++++ usr/klibc/mkstemp.c | 81 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 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/include/sys/elfcommon.h b/usr/include/sys/elfcommon.h index ad5e459..cf2b7ba 100644 --- a/usr/include/sys/elfcommon.h +++ b/usr/include/sys/elfcommon.h @@ -105,8 +105,22 @@ #define AT_PLATFORM 15 /* string identifying CPU for optimizations */ #define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ #define AT_CLKTCK 17 /* frequency at which times() increments */ -/* 18..22 = ? */ +#define AT_FPUCW 18 /* used FPU control word */ +#define AT_DCACHEBSIZE 19 /* data cache block size */ +#define AT_ICACHEBSIZE 20 /* instruction cache block size */ +#define AT_UCACHEBSIZE 21 /* unified cache block size */ +#define AT_IGNOREPPC 22 /* (should be ignored; needed for powerpc) */ #define AT_SECURE 23 /* secure mode boolean */ +#define AT_BASE_PLATFORM 24 /* string identifying real platforms */ +#define AT_RANDOM 25 /* address of 16 random octets */ +/* 26..30 = ? */ +#define AT_EXECFN 31 /* filename of executable */ +#define AT_SYSINFO 32 /* global system page for syscalls etc. */ +#define AT_SYSINFO_EHDR 33 /* related to the above */ +#define AT_L1I_CACHESHAPE 34 /* "shape" of the L1 instruction cache */ +#define AT_L1D_CACHESHAPE 35 /* "shape" of the L1 data cache */ +#define AT_L2_CACHESHAPE 36 /* "shape" of the L2 cache */ +#define AT_L3_CACHESHAPE 37 /* "shape" of the L3 cache */ /* Program header permission flags */ #define PF_X 0x1 diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild index 753ab85..e736803 100644 --- a/usr/klibc/Kbuild +++ b/usr/klibc/Kbuild @@ -47,6 +47,7 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \ time.o utime.o llseek.o nice.o getpriority.o \ qsort.o bsearch.o \ lrand48.o jrand48.o mrand48.o nrand48.o srand48.o seed48.o \ + mkstemp.o \ inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \ inet/inet_ntop.o inet/inet_pton.o inet/bindresvport.o \ send.o recv.o \ diff --git a/usr/klibc/libc_init.c b/usr/klibc/libc_init.c index 8d18820..0bc9047 100644 --- a/usr/klibc/libc_init.c +++ b/usr/klibc/libc_init.c @@ -34,6 +34,9 @@ char **environ; unsigned int __page_size, __page_shift; +/* for use with jrand48() and friends */ +unsigned short __klibc_rand48[3]; + struct auxentry { uintptr_t type; uintptr_t v; @@ -85,6 +88,10 @@ __noreturn __libc_init(uintptr_t * elfdata, void (*onexit) (void)) case AT_PAGESZ: page_size = (unsigned int)(auxentry->v); break; + case AT_RANDOM: + memcpy(__klibc_rand48, (void *)(auxentry->v), + sizeof(__klibc_rand48)); + break; } auxentry++; } diff --git a/usr/klibc/mkstemp.c b/usr/klibc/mkstemp.c new file mode 100644 index 0000000..5dd7240 --- /dev/null +++ b/usr/klibc/mkstemp.c @@ -0,0 +1,81 @@ +/*- + * Compact mkstemp(3)-only implementation, for klibc + * + * Copyright (c) 2009, 2011, 2012 + * Thorsten Glaser <tg at mirbsd.org> + * + * 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> + +/* from libc_main.c pre-filled from AT_RANDOM */ +extern unsigned short __klibc_rand48[3]; + +int +mkstemp(char *template) +{ + int i; + char *cp, *sp; + struct stat sbuf; + + cp = template; + while (*cp) + ++cp; + + sp = cp; + /* generate random suffix */ + while (sp > template && sp[-1] == 'X') { + i = (int)((unsigned int)jrand48(__klibc_rand48) % (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.7.8.3
Hi, after a year, I decided to hack on klibc again. I?ve reworked both the patch to add mkstemp(), discussing to use AT_RANDOM as cheap entropy source on IRC (if there will ever be another entropy consumer, I can quickly write a minimal arc4random() seeded from it, as it has only 16 octets), capable of making a working mksh (static and shared) on amd64/xen, and the m68k support code, leading to (also, static and shared) mksh on it iff compiled with -g (let?s say, GCC is the culprit). The two patches _should_ follow (still not 100% sure how to feed them to sendmail and ensure they end up with the right recipients) and are independent from each other (but for an mksh on m68k, you obviously need both). Cc the Linux/m68k arch list for the m68k patch, to review. (When this works I?m probably going to build mksh-static on dietlibc-less Debian architectures against klibc, pending testing on those platforms of course; the eglibc one is huge.) bye, //mirabilos -- Support mksh as /bin/sh and RoQA dash NOW! ? src:bash (242 (261) bugs: 0 RC, 169 (183) I&N, 73 (78) M&W, 0 F&P) ? src:dash (73 (84) bugs: 3 RC, 27 (30) I&N, 43 (51) M&W, 0 F&P) ? src:mksh (1 bug: 0 RC, 0 I&N, 1 M&W, 0 F&P) http://qa.debian.org/data/bts/graphs/d/dash.png is pretty red, innit?
- fix syscall API and vfork - support 6-argument syscalls - add open/openat special handling for non-regparm arches Signed-off-by: Thorsten Glaser <tg at mirbsd.org> --- usr/klibc/README.klibc | 2 +- usr/klibc/SYSCALLS.def | 4 +- usr/klibc/arch/m68k/Kbuild | 1 + usr/klibc/arch/m68k/open.S | 22 +++++++++++++++++++++ usr/klibc/arch/m68k/openat.S | 26 +++++++++++++++++++++++++ usr/klibc/arch/m68k/syscall.S | 42 +++++++++++++++++++++++++++++++++------- usr/klibc/arch/m68k/vfork.S | 13 +++-------- usr/klibc/open.c | 2 +- usr/klibc/openat.c | 2 +- 9 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 usr/klibc/arch/m68k/open.S create mode 100644 usr/klibc/arch/m68k/openat.S diff --git a/usr/klibc/README.klibc b/usr/klibc/README.klibc index b4135cb..5417049 100644 --- a/usr/klibc/README.klibc +++ b/usr/klibc/README.klibc @@ -44,7 +44,7 @@ b) If you're cross-compiling, you need to set KLIBCARCH to the i386: Working ia64: Working static, shared untested m32r: Untested - m68k: Untested + m68k: Working m68knommu: Not yet ported mips: Working mips64: Not yet ported diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def index 6ed6bdf..12aef49 100644 --- a/usr/klibc/SYSCALLS.def +++ b/usr/klibc/SYSCALLS.def @@ -154,8 +154,8 @@ int getcwd::__getcwd(char *, size_t); /* * I/O operations */ -<!i386,64> int open::__open(const char *, int, mode_t); -<?!i386,64> int openat::__openat(int, const char *, int, mode_t); +<!i386,m68k,64> int open::__open(const char *, int, mode_t); +<?!i386,m68k,64> int openat::__openat(int, const char *, int, mode_t); <64> int open(const char *, int, mode_t); ssize_t read(int, void *, size_t); ssize_t write(int, const void *, size_t); diff --git a/usr/klibc/arch/m68k/Kbuild b/usr/klibc/arch/m68k/Kbuild index 8d6137c..d56ae0e 100644 --- a/usr/klibc/arch/m68k/Kbuild +++ b/usr/klibc/arch/m68k/Kbuild @@ -3,6 +3,7 @@ # klib-y := setjmp.o syscall.o vfork.o +klib-y += open.o openat.o always := crt0.o targets := crt0.o diff --git a/usr/klibc/arch/m68k/open.S b/usr/klibc/arch/m68k/open.S new file mode 100644 index 0000000..c9a7ee3 --- /dev/null +++ b/usr/klibc/arch/m68k/open.S @@ -0,0 +1,22 @@ +/* + * arch/m68k/open.S + * + * Handle the open() system call - oddball due to the varadic + * prototype, which forces the use of the cdecl calling convention, + * and the need for O_LARGEFILE. + */ + +#include <asm/unistd.h> + +/* <asm/fcntl.h>, despite the name, isn't assembly-safe */ +#define O_LARGEFILE 0400000 + + .globl open + .type open, at function + +open: + or.l # O_LARGEFILE, 8(%sp) + move.l # __NR_open, %d0 + br __syscall_common + + .size open,.-open diff --git a/usr/klibc/arch/m68k/openat.S b/usr/klibc/arch/m68k/openat.S new file mode 100644 index 0000000..25d8a1a --- /dev/null +++ b/usr/klibc/arch/m68k/openat.S @@ -0,0 +1,26 @@ +/* + * arch/m68k/openat.S + * + * Handle the openat() system call - oddball due to the varadic + * prototype, which forces the use of the cdecl calling convention, + * and the need for O_LARGEFILE. + */ + +#include <asm/unistd.h> + +/* <asm/fcntl.h>, despite the name, isn't assembly-safe */ +#define O_LARGEFILE 0400000 + +#ifdef __NR_openat /* Don't build if kernel headers too old */ + + .globl openat + .type openat, at function + +openat: + or.l # O_LARGEFILE, 12(%sp) + move.l # __NR_openat, %d0 + br __syscall_common + + .size openat,.-openat + +#endif diff --git a/usr/klibc/arch/m68k/syscall.S b/usr/klibc/arch/m68k/syscall.S index 966c92d..c909e2a 100644 --- a/usr/klibc/arch/m68k/syscall.S +++ b/usr/klibc/arch/m68k/syscall.S @@ -11,17 +11,43 @@ .globl __syscall_common .type __syscall_common, @function __syscall_common: - movem.l %d2-%d6, -(%sp) /* 5 registers saved */ - movem.l 24(%sp), %d1-%d6 + /* + * According to eglibc, separate moves are faster than movem; + * speed is important and this code is not duplicated anyway, + * so we do the same here. We use %a1 as scratch register for + * saving; syscall arguments are to be in %d1 to %d5 and %a0. + */ + move.l 24(%sp), %a0 /* orig.sp+24: arg 6 */ + move.l %d5, -(%sp) /* push d5 (callee saved) */ + move.l 24(%sp), %d5 /* orig.sp+20: arg 5 */ + move.l %d4, -(%sp) /* push d4 (callee saved) */ + move.l 24(%sp), %d4 /* orig.sp+16: arg 4 */ + move.l %d3, -(%sp) /* push d3 (callee saved) */ + move.l 24(%sp), %d3 /* orig.sp+12: arg 3 */ + move.l %d2, %a1 /* save d2 (callee saved) in a1 */ + move.l 20(%sp), %d2 /* orig.sp+8: arg 2 */ + move.l 16(%sp), %d1 /* orig.sp+4: arg 1 */ trap #0 - cmpi.l #-4095, %d0 - blt.l 1f + move.l %a1, %d2 /* restore d2 from a1 (scratch) */ + move.l (%sp)+, %d3 /* pop d3..d5, see above */ + move.l (%sp)+, %d4 + move.l (%sp)+, %d5 + + /* syscall is done, result in %d0, registers are restored */ + .globl __syscall_checkandout +__syscall_checkandout: + /* now check for error */ + cmp.l #-4095, %d0 + bcs.l 1f /* jump if _not_ error */ + + /* prepare for error return */ neg.l %d0 move.l %d0, (errno) - moveq #-1, %d0 -1: - movea.l %d0, %a0 /* Redundant return */ - movem.l (%sp)+, %d2-%d6 /* Restore registers */ + move.l #-1, %d0 + /* fallthrough into common return path */ + +1: /* copy return value to %a0 for syscalls returning pointers */ + move.l %d0, %a0 rts .size __syscall_common,.-__syscall_common diff --git a/usr/klibc/arch/m68k/vfork.S b/usr/klibc/arch/m68k/vfork.S index a3a7e44..98170a6 100644 --- a/usr/klibc/arch/m68k/vfork.S +++ b/usr/klibc/arch/m68k/vfork.S @@ -15,14 +15,9 @@ vfork: move.l (%sp)+, %d1 /* Return address */ move.l # __NR_vfork, %d0 trap #0 - move.l %d1, -(%sp) - cmpi.l #-4095, %d0 - blt.l 1f - neg.l %d0 - move.l %d0, (errno) - moveq #-1, %d0 -1: - movea.l %d0, %a0 - rts + move.l %d1, -(%sp) /* restore stack */ + + /* fallthrough into common code from syscall.S */ + bra __syscall_checkandout .size vfork, .-vfork diff --git a/usr/klibc/open.c b/usr/klibc/open.c index 9b0897a..126f6db 100644 --- a/usr/klibc/open.c +++ b/usr/klibc/open.c @@ -10,7 +10,7 @@ #include <fcntl.h> #include <bitsize.h> -#if _BITSIZE == 32 && !defined(__i386__) +#if _BITSIZE == 32 && !defined(__i386__) && !defined(__m68k__) extern int __open(const char *, int, mode_t); diff --git a/usr/klibc/openat.c b/usr/klibc/openat.c index 83c87cd..8e5baa0 100644 --- a/usr/klibc/openat.c +++ b/usr/klibc/openat.c @@ -10,7 +10,7 @@ #include <fcntl.h> #include <bitsize.h> -#if _BITSIZE == 32 && !defined(__i386__) && defined(__NR_openat) +#if _BITSIZE == 32 && !defined(__i386__) && !defined(__m68k__) && defined(__NR_openat) extern int __openat(int, const char *, int, mode_t); -- 1.7.8.3
Thorsten,> after a year, I decided to hack on klibc again. I?ve reworked > both the patch to add mkstemp(), discussing to use AT_RANDOM > as cheap entropy source on IRC (if there will ever be another > entropy consumer, I can quickly write a minimal arc4random() > seeded from it, as it has only 16 octets), capable of making > a working mksh (static and shared) on amd64/xen, and the m68k > support code, leading to (also, static and shared) mksh on it > iff compiled with -g (let?s say, GCC is the culprit). > > The two patches _should_ follow (still not 100% sure how to > feed them to sendmail and ensure they end up with the rightYou appear to have failed. Care to post it to your p.d.o page? (I've never tried talking to sendmail directly except for low level testing - you'll have to manually prepare a valid mail message with the attachments embedded for that to work I guess. That's what mutt and friends are for)> recipients) and are independent from each other (but for an > mksh on m68k, you obviously need both). > > Cc the Linux/m68k arch list for the m68k patch, to review. > > (When this works I?m probably going to build mksh-static on > dietlibc-less Debian architectures against klibc, pending > testing on those platforms of course; the eglibc one is huge.)Good luck with that. Cheers, Michael
Dixi quod?>- fix syscall API and vfork >- support 6-argument syscalls >- add open/openat special handling for non-regparm archesFor the archives, and to keep everyone in the loop (said this on IRC already, in #klibc): This patch is part of klibc (2.0~rc2-0.1) uploaded to Debian unstable (which otherwise is git HEAD as of 11 Feb 2012). I?ve built mksh against it (using an older mkstemp.c externally, since the latest patch requires the libc_init.c change, which I didn?t add to the Debian package) dynamically, and it worked. Furthermore, I?ve built a minimal-ish sv4cpio archive (to be passed as initrd) on m68k consisting of: ? klibc-utils ? that mksh binary ? a /init shell script to mount stuff and give a shell ragnar76 successfully booted that (with the kernel image from linux-image-3.2.0-1-atari_3.2.4-1_m68k.deb of proper Debian unstable) on real hardware. Andreas, if you would like a different jump instruction, feel free to update my patch, as I bow to your superiour knowledge. Otherwise I submit this as-is, tested. bye, //mirabilos -- Support mksh as /bin/sh and RoQA dash NOW! ? src:bash (246 (265) bugs: 1 RC, 172 (186) I&N, 73 (78) M&W, 0 F&P) ? src:dash (74 (85) bugs: 3 RC, 27 (30) I&N, 44 (52) M&W, 0 F&P) ? src:mksh (1 bug: 0 RC, 0 I&N, 1 M&W, 0 F&P) http://qa.debian.org/data/bts/graphs/d/dash.png is pretty red, innit?
Dixi quod?>patch to add mkstemp()I rescind that patch, mksh does not use mkstemp() any more. (This is inspired by klibc, but also by other platforms mksh runs on which lack it, as tempnam() is no real fallback.)>m68k support code, leading to (also, static and shared) mksh >on it iff compiled with -g (let?s say, GCC is the culprit).With -g and without -O2 or -Os. Weird.>(When this works I?m probably going to build mksh-static on >dietlibc-less Debian architectures against klibc, pendingToday?s mksh uploads to Debian try klibc first. Asides from the m68k problem above I believe powerpc may be broken, but let?s see when the results are there. mksh _has_ proven to be a good compiler/toolchain/library/system test in the past. bye, //mirabilos -- "Using Lynx is like wearing a really good pair of shades: cuts out the glare and harmful UV (ultra-vanity), and you feel so-o-o COOL." -- Henry Nelson, March 1999