to speed up mksh, get rid of arc4random(3) uses and use the LCG always;

depend on ASLR for seeding
This commit is contained in:
tg 2010-07-04 17:33:58 +00:00
parent 2d6b4acba1
commit 4cbb5a9d46
8 changed files with 186 additions and 279 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.452 2010/05/13 18:41:13 tg Exp $' srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.453 2010/07/04 17:33:53 tg Exp $'
#- #-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
# Thorsten Glaser <tg@mirbsd.org> # Thorsten Glaser <tg@mirbsd.org>
@ -1200,51 +1200,6 @@ EOF
# #
# Environment: library functions # Environment: library functions
# #
ac_testn arc4random <<-'EOF'
#include <sys/types.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
extern u_int32_t arc4random(void);
int main(void) { return ((int)(arc4random() & 0xFF)); }
EOF
save_LIBS=$LIBS
if test 0 = $HAVE_ARC4RANDOM; then
test -f arc4random.c || if test -f "$srcdir/arc4random.c"; then
# ensure isolation of source directory from build directory
cp "$srcdir/arc4random.c" .
fi
if test -f arc4random.c; then
ac_testn can_uint8t '' "for uint8_t" <<-'EOF'
#include <sys/types.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
int main(void) { return (1 - (uint8_t)1); }
EOF
test $HAVE_CAN_UINT8T = 1 || \
CPPFLAGS="$CPPFLAGS -D\"uint8_t=unsigned char\""
ac_header sys/sysctl.h
addsrcs '!' HAVE_ARC4RANDOM arc4random.c
HAVE_ARC4RANDOM=1
LIBS="$LIBS arc4random.c"
fi
fi
ac_cppflags ARC4RANDOM
ac_test arc4random_pushb arc4random 0 <<-'EOF'
#include <sys/types.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
extern uint32_t arc4random_pushb(void *, size_t);
int main(int ac, char *av[]) { return ((int)(arc4random_pushb(*av,
(size_t)ac)) & 0xFF); }
EOF
LIBS=$save_LIBS
ac_testn flock_ex '' 'flock and mmap' <<-'EOF' ac_testn flock_ex '' 'flock and mmap' <<-'EOF'
#include <sys/types.h> #include <sys/types.h>
#include <sys/file.h> #include <sys/file.h>
@ -1366,18 +1321,6 @@ EOF
# #
save_CC=$CC; save_LDFLAGS=$LDFLAGS; save_LIBS=$LIBS save_CC=$CC; save_LDFLAGS=$LDFLAGS; save_LIBS=$LIBS
CC="$CC -c -o $tcfn"; LDFLAGS=; LIBS= CC="$CC -c -o $tcfn"; LDFLAGS=; LIBS=
ac_test '!' arc4random_decl arc4random 1 'if arc4random() does not need to be declared' <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
long arc4random(void); /* this clashes if defined before */
int main(void) { return ((int)arc4random()); }
EOF
ac_test '!' arc4random_pushb_decl arc4random_pushb 1 'if arc4random_pushb() does not need to be declared' <<-'EOF'
#define MKSH_INCLUDES_ONLY
#include "sh.h"
int arc4random_pushb(char, int); /* this clashes if defined before */
int main(int ac, char *av[]) { return ((int)arc4random_pushb(**av, ac)); }
EOF
ac_test '!' flock_decl flock_ex 1 'if flock() does not need to be declared' <<-'EOF' ac_test '!' flock_decl flock_ex 1 'if flock() does not need to be declared' <<-'EOF'
#define MKSH_INCLUDES_ONLY #define MKSH_INCLUDES_ONLY
#include "sh.h" #include "sh.h"

128
jobs.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.68 2010/07/04 13:36:42 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.69 2010/07/04 17:33:54 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
#define mksh_killpg killpg #define mksh_killpg killpg
@ -340,15 +340,12 @@ exchild(struct op *t, int flags,
{ {
static Proc *last_proc; /* for pipelines */ static Proc *last_proc; /* for pipelines */
int i, rv = 0, forksleep; int rv = 0, forksleep;
sigset_t omask; sigset_t omask;
Proc *p;
Job *j;
struct { struct {
#if !HAVE_ARC4RANDOM Proc *p;
pid_t thepid; Job *j;
#endif pid_t cldpid;
unsigned char ischild;
} pi; } pi;
if (flags & XEXEC) if (flags & XEXEC)
@ -361,99 +358,93 @@ exchild(struct op *t, int flags,
/* no SIGCHLDs while messing with job and process lists */ /* no SIGCHLDs while messing with job and process lists */
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
p = new_proc(); pi.p = new_proc();
p->next = NULL; pi.p->next = NULL;
p->state = PRUNNING; pi.p->state = PRUNNING;
p->status = 0; pi.p->status = 0;
p->pid = 0; pi.p->pid = 0;
/* link process into jobs list */ /* link process into jobs list */
if (flags & XPIPEI) { /* continuing with a pipe */ if (flags & XPIPEI) {
/* continuing with a pipe */
if (!last_job) if (!last_job)
internal_errorf( internal_errorf(
"exchild: XPIPEI and no last_job - pid %d", "exchild: XPIPEI and no last_job - pid %d",
(int)procpid); (int)procpid);
j = last_job; pi.j = last_job;
if (last_proc) if (last_proc)
last_proc->next = p; last_proc->next = pi.p;
last_proc = p; last_proc = pi.p;
} else { } else {
j = new_job(); /* fills in j->job */ pi.j = new_job(); /* fills in pi.j->job */
/* /*
* we don't consider XXCOMs foreground since they don't get * we don't consider XXCOMs foreground since they don't get
* tty process group and we don't save or restore tty modes. * tty process group and we don't save or restore tty modes.
*/ */
j->flags = (flags & XXCOM) ? JF_XXCOM : pi.j->flags = (flags & XXCOM) ? JF_XXCOM :
((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE)); ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
timerclear(&j->usrtime); timerclear(&pi.j->usrtime);
timerclear(&j->systime); timerclear(&pi.j->systime);
j->state = PRUNNING; pi.j->state = PRUNNING;
j->pgrp = 0; pi.j->pgrp = 0;
j->ppid = procpid; pi.j->ppid = procpid;
j->age = ++njobs; pi.j->age = ++njobs;
j->proc_list = p; pi.j->proc_list = pi.p;
j->coproc_id = 0; pi.j->coproc_id = 0;
last_job = j; last_job = pi.j;
last_proc = p; last_proc = pi.p;
put_job(j, PJ_PAST_STOPPED); put_job(pi.j, PJ_PAST_STOPPED);
} }
snptreef(p->command, sizeof(p->command), "%T", t); snptreef(pi.p->command, sizeof(pi.p->command), "%T", t);
/* create child process */ /* create child process */
forksleep = 1; forksleep = 1;
while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) { while ((pi.cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
if (intrsig) /* allow user to ^C out... */ if (intrsig) /* allow user to ^C out... */
break; break;
sleep(forksleep); sleep(forksleep);
forksleep <<= 1; forksleep <<= 1;
} }
if (i < 0) { if (pi.cldpid < 0) {
kill_job(j, SIGKILL); kill_job(pi.j, SIGKILL);
remove_job(j, "fork failed"); remove_job(pi.j, "fork failed");
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
errorf("cannot fork - try again"); errorf("cannot fork - try again");
} }
#if !HAVE_ARC4RANDOM pi.p->pid = pi.cldpid ? pi.cldpid : (procpid = getpid());
#ifdef DEBUG
/* reduce extra 3 bytes of entropy, for Valgrind */
memset(&pi, 0, sizeof(pi));
#endif
pi.thepid =
#endif
p->pid = (pi.ischild = i == 0) ? (procpid = getpid()) : i;
#if !HAVE_ARC4RANDOM
/* /*
* ensure next child gets a (slightly) different $RANDOM sequence * ensure next child gets a (slightly) different $RANDOM sequence
* from its parent process and other child processes * from its parent process and other child processes
*/ */
change_random(&pi, sizeof(pi)); change_random(&pi, sizeof(pi));
#endif
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
/* job control set up */ /* job control set up */
if (Flag(FMONITOR) && !(flags&XXCOM)) { if (Flag(FMONITOR) && !(flags&XXCOM)) {
int dotty = 0; int dotty = 0;
if (j->pgrp == 0) { /* First process */ if (pi.j->pgrp == 0) { /* First process */
j->pgrp = p->pid; pi.j->pgrp = pi.p->pid;
dotty = 1; dotty = 1;
} }
/* set pgrp in both parent and child to deal with race /* set pgrp in both parent and child to deal with race
* condition * condition
*/ */
setpgid(p->pid, j->pgrp); setpgid(pi.p->pid, pi.j->pgrp);
if (ttypgrp_ok && dotty && !(flags & XBGND)) if (ttypgrp_ok && dotty && !(flags & XBGND))
tcsetpgrp(tty_fd, j->pgrp); tcsetpgrp(tty_fd, pi.j->pgrp);
} }
#endif #endif
/* used to close pipe input fd */ /* used to close pipe input fd */
if (close_fd >= 0 && (((flags & XPCLOSE) && !pi.ischild) || if (close_fd >= 0 && (((flags & XPCLOSE) && pi.cldpid) ||
((flags & XCCLOSE) && pi.ischild))) ((flags & XCCLOSE) && !pi.cldpid)))
close(close_fd); close(close_fd);
if (pi.ischild) { /* child */ if (!pi.cldpid) {
/* child */
/* Do this before restoring signal */ /* Do this before restoring signal */
if (flags & XCOPROC) if (flags & XCOPROC)
coproc_cleanup(false); coproc_cleanup(false);
@ -465,8 +456,8 @@ exchild(struct op *t, int flags,
* their inherited values. * their inherited values.
*/ */
if (Flag(FMONITOR) && !(flags & XXCOM)) { if (Flag(FMONITOR) && !(flags & XXCOM)) {
for (i = NELEM(tt_sigs); --i >= 0; ) for (forksleep = NELEM(tt_sigs); --forksleep >= 0; )
setsig(&sigtraps[tt_sigs[i]], SIG_DFL, setsig(&sigtraps[tt_sigs[forksleep]], SIG_DFL,
SS_RESTORE_DFL|SS_FORCE); SS_RESTORE_DFL|SS_FORCE);
} }
#endif #endif
@ -484,12 +475,12 @@ exchild(struct op *t, int flags,
setsig(&sigtraps[SIGQUIT], SIG_IGN, setsig(&sigtraps[SIGQUIT], SIG_IGN,
SS_RESTORE_IGN|SS_FORCE); SS_RESTORE_IGN|SS_FORCE);
if ((!(flags & (XPIPEI | XCOPROC))) && if ((!(flags & (XPIPEI | XCOPROC))) &&
((i = open("/dev/null", 0)) > 0)) { ((forksleep = open("/dev/null", 0)) > 0)) {
(void)ksh_dup2(i, 0, true); (void)ksh_dup2(forksleep, 0, true);
close(i); close(forksleep);
} }
} }
remove_job(j, "child"); /* in case of $(jobs) command */ remove_job(pi.j, "child"); /* in case of $(jobs) command */
nzombie = 0; nzombie = 0;
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
ttypgrp_ok = false; ttypgrp_ok = false;
@ -513,24 +504,27 @@ exchild(struct op *t, int flags,
/* shell (parent) stuff */ /* shell (parent) stuff */
if (!(flags & XPIPEO)) { /* last process in a job */ if (!(flags & XPIPEO)) { /* last process in a job */
j_startjob(j); j_startjob(pi.j);
if (flags & XCOPROC) { if (flags & XCOPROC) {
j->coproc_id = coproc.id; pi.j->coproc_id = coproc.id;
coproc.njobs++; /* n jobs using co-process output */ /* n jobs using co-process output */
coproc.job = (void *) j; /* j using co-process input */ coproc.njobs++;
/* j using co-process input */
coproc.job = (void *)pi.j;
} }
if (flags & XBGND) { if (flags & XBGND) {
j_set_async(j); j_set_async(pi.j);
if (Flag(FTALKING)) { if (Flag(FTALKING)) {
shf_fprintf(shl_out, "[%d]", j->job); shf_fprintf(shl_out, "[%d]", pi.j->job);
for (p = j->proc_list; p; p = p->next) for (pi.p = pi.j->proc_list; pi.p;
pi.p = pi.p->next)
shf_fprintf(shl_out, " %d", shf_fprintf(shl_out, " %d",
(int)p->pid); (int)pi.p->pid);
shf_putchar('\n', shl_out); shf_putchar('\n', shl_out);
shf_flush(shl_out); shf_flush(shl_out);
} }
} else } else
rv = j_waitj(j, JW_NONE, "jw:last proc"); rv = j_waitj(pi.j, JW_NONE, "jw:last proc");
} }
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);

45
main.c
View File

@ -33,7 +33,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.165 2010/05/22 12:49:15 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/main.c,v 1.166 2010/07/04 17:33:55 tg Exp $");
extern char **environ; extern char **environ;
@ -92,8 +92,7 @@ static const char *initcoms[] = {
static int initio_done; static int initio_done;
static struct env env; struct env *e = &kshstate_v.env_;
struct env *e = &env;
void void
chvt_reinit(void) chvt_reinit(void)
@ -102,10 +101,6 @@ chvt_reinit(void)
ksheuid = geteuid(); ksheuid = geteuid();
kshpgrp = getpgrp(); kshpgrp = getpgrp();
kshppid = getppid(); kshppid = getppid();
#if !HAVE_ARC4RANDOM
change_random(&kshstate_, sizeof(kshstate_));
#endif
} }
Source * Source *
@ -140,8 +135,8 @@ mksh_init(int argc, const char *argv[])
ainit(&aperm); /* initialise permanent Area */ ainit(&aperm); /* initialise permanent Area */
/* set up base environment */ /* set up base environment */
env.type = E_NONE; kshstate_v.env_.type = E_NONE;
ainit(&env.area); ainit(&kshstate_v.env_.area);
newblock(); /* set up global l->vars and l->funs */ newblock(); /* set up global l->vars and l->funs */
/* Do this first so output routines (eg, errorf, shellf) can work */ /* Do this first so output routines (eg, errorf, shellf) can work */
@ -294,13 +289,10 @@ mksh_init(int argc, const char *argv[])
vp->flag |= INT_U; vp->flag |= INT_U;
setint((vp = global("PPID")), (mksh_uari_t)kshppid); setint((vp = global("PPID")), (mksh_uari_t)kshppid);
vp->flag |= INT_U; vp->flag |= INT_U;
setint((vp = global("RANDOM")), (mksh_uari_t)hash(kshname)); setint((vp = global("RANDOM")), (mksh_uari_t)evilhash(kshname));
vp->flag |= INT_U; vp->flag |= INT_U;
setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid); setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid);
vp->flag |= INT_U; vp->flag |= INT_U;
#if HAVE_ARC4RANDOM
Flag(FARC4RANDOM) = 1; /* initialised */
#endif
/* Set this before parsing arguments */ /* Set this before parsing arguments */
#if HAVE_SETRESUGID #if HAVE_SETRESUGID
@ -469,9 +461,14 @@ main(int argc, const char *argv[])
{ {
Source *s; Source *s;
if ((s = mksh_init(argc, argv))) kshstate_v.lcg_state_ = 5381;
if ((s = mksh_init(argc, argv))) {
/* put more entropy into the LCG */
change_random(s, sizeof(*s));
/* doesnt return */ /* doesnt return */
shell(s, true); shell(s, true);
}
return (1); return (1);
} }
@ -1300,26 +1297,6 @@ static int tnamecmp(const void *, const void *);
static struct tbl *ktscan(struct table *, const char *, uint32_t, static struct tbl *ktscan(struct table *, const char *, uint32_t,
struct tbl ***); struct tbl ***);
/* Bob Jenkins' one-at-a-time hash */
uint32_t
oaathash_full(register const uint8_t *bp)
{
register uint32_t h = 0;
register uint8_t c;
while ((c = *bp++)) {
h += c;
h += h << 10;
h ^= h >> 6;
}
h += h << 3;
h ^= h >> 11;
h += h << 15;
return (h);
}
static void static void
texpand(struct table *tp, size_t nsize) texpand(struct table *tp, size_t nsize)
{ {

5
misc.c
View File

@ -29,7 +29,7 @@
#include <grp.h> #include <grp.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.138 2010/01/29 09:34:29 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.139 2010/07/04 17:33:55 tg Exp $");
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */ unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
@ -1266,6 +1266,9 @@ chvt(const char *fn)
struct stat sb; struct stat sb;
int fd; int fd;
/* for entropy */
kshstate_f.h = evilhash(fn);
if (*fn == '-') { if (*fn == '-') {
memcpy(dv, "-/dev/null", sizeof("-/dev/null")); memcpy(dv, "-/dev/null", sizeof("-/dev/null"));
fn = dv + 1; fn = dv + 1;

16
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.226 2010/05/13 18:47:50 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.227 2010/07/04 17:33:56 tg Exp $
.\" $OpenBSD: ksh.1,v 1.134 2010/05/10 21:04:54 jmc Exp $ .\" $OpenBSD: ksh.1,v 1.134 2010/05/10 21:04:54 jmc Exp $
.\"- .\"-
.\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 .\" Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
@ -71,7 +71,7 @@
.\" with -mandoc, it might implement .Mx itself, but we want to .\" with -mandoc, it might implement .Mx itself, but we want to
.\" use our own definition. And .Dd must come *first*, always. .\" use our own definition. And .Dd must come *first*, always.
.\" .\"
.Dd $Mdocdate: May 13 2010 $ .Dd $Mdocdate: July 4 2010 $
.\" .\"
.\" Check which macro package we use .\" Check which macro package we use
.\" .\"
@ -1923,11 +1923,7 @@ if the shell doesn't know where it is.
Every time Every time
.Ev RANDOM .Ev RANDOM
is referenced, it is assigned a 15-bit pseudo-random number, i.e. between is referenced, it is assigned a 15-bit pseudo-random number, i.e. between
0 and 32767, first, which is taken from 0 and 32767, first, which is taken from a Linear Congruential PRNG.
.Xr arc4random 3
if available,
a Linear Congruential PRNG
otherwise.
.It Ev REPLY .It Ev REPLY
Default parameter for the Default parameter for the
.Ic read .Ic read
@ -3856,11 +3852,6 @@ during file name generation.
Print commands and parameter assignments when they are executed, preceded by Print commands and parameter assignments when they are executed, preceded by
the value of the value of
.Ev PS4 . .Ev PS4 .
.It Ic arc4random
If this shell option, which cannot be unset, exists,
.Xr arc4random 3
is used for the value of
.Ev RANDOM .
.It Ic bgnice .It Ic bgnice
Background jobs are run with lower priority. Background jobs are run with lower priority.
.It Ic braceexpand .It Ic braceexpand
@ -5929,7 +5920,6 @@ Privileged shell profile.
.Xr pipe 2 , .Xr pipe 2 ,
.Xr rename 2 , .Xr rename 2 ,
.Xr wait 2 , .Xr wait 2 ,
.Xr arc4random 3 ,
.Xr getopt 3 , .Xr getopt 3 ,
.Xr nl_langinfo 3 , .Xr nl_langinfo 3 ,
.Xr setlocale 3 , .Xr setlocale 3 ,

97
sh.h
View File

@ -150,7 +150,7 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.393 2010/07/04 13:36:43 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.394 2010/07/04 17:33:57 tg Exp $");
#endif #endif
#define MKSH_VERSION "R39 2010/05/22" #define MKSH_VERSION "R39 2010/05/22"
@ -272,16 +272,6 @@ typedef int bool;
/* OS-dependent additions (functions, variables, by OS) */ /* OS-dependent additions (functions, variables, by OS) */
#if !HAVE_ARC4RANDOM_DECL
extern u_int32_t arc4random(void);
extern void arc4random_addrandom(unsigned char *, int)
MKSH_A_BOUNDED(string, 1, 2);
#endif
#if !HAVE_ARC4RANDOM_PUSHB_DECL
extern uint32_t arc4random_pushb(const void *, size_t);
#endif
#if !HAVE_FLOCK_DECL #if !HAVE_FLOCK_DECL
extern int flock(int, int); extern int flock(int, int);
#endif #endif
@ -361,25 +351,6 @@ typedef uint32_t mksh_uari_t;
#define LINE 4096 /* input line size */ #define LINE 4096 /* input line size */
EXTERN struct {
const char *kshname_; /* $0 */
pid_t kshpid_; /* $$, shell PID */
pid_t procpid_; /* PID of executing process */
pid_t kshpgrp_; /* process group of shell */
uid_t ksheuid_; /* effective UID of shell */
pid_t kshppid_; /* PID of parent of shell */
int exstat_; /* exit status */
int subst_exstat_; /* exit status of last $(..)/`..` */
} kshstate_;
#define kshname kshstate_.kshname_
#define kshpid kshstate_.kshpid_
#define procpid kshstate_.procpid_
#define kshpgrp kshstate_.kshpgrp_
#define ksheuid kshstate_.ksheuid_
#define kshppid kshstate_.kshppid_
#define exstat kshstate_.exstat_
#define subst_exstat kshstate_.subst_exstat_
EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */
EXTERN const char initvsn[] I__("KSH_VERSION=@(#)MIRBSD KSH " MKSH_VERSION); EXTERN const char initvsn[] I__("KSH_VERSION=@(#)MIRBSD KSH " MKSH_VERSION);
#define KSH_VERSION (initvsn + /* "KSH_VERSION=@(#)" */ 16) #define KSH_VERSION (initvsn + /* "KSH_VERSION=@(#)" */ 16)
@ -514,6 +485,18 @@ EXTERN Area aperm; /* permanent object space */
#define APERM &aperm #define APERM &aperm
#define ATEMP &e->area #define ATEMP &e->area
/*
* flags (the order of these enums MUST match the order in misc.c(options[]))
*/
enum sh_flag {
#define SHFLAGS_ENUMS
#include "sh_flags.h"
FNFLAGS /* (place holder: how many flags are there) */
};
#define Flag(f) (kshstate_v.shell_flags_[(int)(f)])
#define UTFMODE Flag(FUNICODE)
/* /*
* parsing & execution environment * parsing & execution environment
*/ */
@ -561,6 +544,44 @@ extern struct env {
#define LSHELL 8 /* return to interactive shell() */ #define LSHELL 8 /* return to interactive shell() */
#define LAEXPR 9 /* error in arithmetic expression */ #define LAEXPR 9 /* error in arithmetic expression */
/*
* some kind of global shell state, for change_random() mostly
*/
EXTERN struct {
/* for change_random */
struct timeval cr_tv; /* timestamp */
const void *cr_dp; /* argument address */
size_t cr_dsz; /* argument length */
uint32_t lcg_state_; /* previous LCG state */
/* global state */
pid_t procpid_; /* PID of executing process */
int exstat_; /* exit status */
int subst_exstat_; /* exit status of last $(..)/`..` */
struct env env_; /* top-level parsing & execution env. */
uint8_t shell_flags_[FNFLAGS];
} kshstate_v;
EXTERN struct {
const char *kshname_; /* $0 */
pid_t kshpid_; /* $$, shell PID */
pid_t kshpgrp_; /* process group of shell */
uid_t ksheuid_; /* effective UID of shell */
pid_t kshppid_; /* PID of parent of shell */
uint32_t h; /* some kind of hash */
} kshstate_f;
#define kshname kshstate_f.kshname_
#define kshpid kshstate_f.kshpid_
#define procpid kshstate_v.procpid_
#define kshpgrp kshstate_f.kshpgrp_
#define ksheuid kshstate_f.ksheuid_
#define kshppid kshstate_f.kshppid_
#define exstat kshstate_v.exstat_
#define subst_exstat kshstate_v.subst_exstat_
/* evil hack: return hash(kshstate_f concat (kshstate_f'.h:=hash(arg))) */
uint32_t evilhash(const char *);
/* option processing */ /* option processing */
#define OF_CMDLINE 0x01 /* command line */ #define OF_CMDLINE 0x01 /* command line */
#define OF_SET 0x02 /* set builtin */ #define OF_SET 0x02 /* set builtin */
@ -576,20 +597,6 @@ struct shoption {
}; };
extern const struct shoption options[]; extern const struct shoption options[];
/*
* flags (the order of these enums MUST match the order in misc.c(options[]))
*/
enum sh_flag {
#define SHFLAGS_ENUMS
#include "sh_flags.h"
FNFLAGS /* (place holder: how many flags are there) */
};
#define Flag(f) (shell_flags[(int)(f)])
#define UTFMODE Flag(FUNICODE)
EXTERN unsigned char shell_flags[FNFLAGS];
/* null value for variable; comparision pointer for unset */ /* null value for variable; comparision pointer for unset */
EXTERN char null[] I__(""); EXTERN char null[] I__("");
/* helpers for string pooling */ /* helpers for string pooling */
@ -1635,9 +1642,7 @@ const char *skip_wdvarname(const char *, int);
int is_wdvarname(const char *, int); int is_wdvarname(const char *, int);
int is_wdvarassign(const char *); int is_wdvarassign(const char *);
char **makenv(void); char **makenv(void);
#if !HAVE_ARC4RANDOM
void change_random(const void *, size_t); void change_random(const void *, size_t);
#endif
void change_winsz(void); void change_winsz(void);
int array_ref_len(const char *); int array_ref_len(const char *);
char *arrayname(const char *); char *arrayname(const char *);

View File

@ -1,5 +1,5 @@
#if defined(SHFLAGS_DEFNS) #if defined(SHFLAGS_DEFNS)
__RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.5 2010/01/28 15:18:51 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.6 2010/07/04 17:33:58 tg Exp $");
#define FN(sname,cname,ochar,flags) /* nothing */ #define FN(sname,cname,ochar,flags) /* nothing */
#elif defined(SHFLAGS_ENUMS) #elif defined(SHFLAGS_ENUMS)
#define FN(sname,cname,ochar,flags) cname, #define FN(sname,cname,ochar,flags) cname,
@ -21,11 +21,6 @@ __RCSID("$MirOS: src/bin/mksh/sh_flags.h,v 1.5 2010/01/28 15:18:51 tg Exp $");
/* -a all new parameters are created with the export attribute */ /* -a all new parameters are created with the export attribute */
F0("allexport", FEXPORT, 'a', OF_ANY) F0("allexport", FEXPORT, 'a', OF_ANY)
#if HAVE_ARC4RANDOM
/* ./. backwards compat: available if arc4random(3) is used for $RANDOM */
FN("arc4random", FARC4RANDOM, 0, OF_INTERNAL)
#endif
#if HAVE_NICE #if HAVE_NICE
/* ./. bgnice */ /* ./. bgnice */
FN("bgnice", FBGNICE, 0, OF_ANY) FN("bgnice", FBGNICE, 0, OF_ANY)

108
var.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.104 2010/01/28 20:26:52 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/var.c,v 1.105 2010/07/04 17:33:58 tg Exp $");
/* /*
* Variables * Variables
@ -46,12 +46,9 @@ static int getint(struct tbl *, mksh_ari_t *, bool);
static mksh_ari_t intval(struct tbl *); static mksh_ari_t intval(struct tbl *);
static struct tbl *arraysearch(struct tbl *, uint32_t); static struct tbl *arraysearch(struct tbl *, uint32_t);
static const char *array_index_calc(const char *, bool *, uint32_t *); static const char *array_index_calc(const char *, bool *, uint32_t *);
#if !HAVE_ARC4RANDOM
static uint32_t oaathash_update(register uint32_t, register const uint8_t *, static uint32_t oaathash_update(register uint32_t, register const uint8_t *,
register size_t); register size_t);
static uint32_t oaathash_finalise(register uint32_t);
static uint32_t lcg_state = 5381;
#endif
uint8_t set_refflag = 0; uint8_t set_refflag = 0;
@ -982,7 +979,7 @@ makenv(void)
return ((char **)XPclose(denv)); return ((char **)XPclose(denv));
} }
#if !HAVE_ARC4RANDOM /* Bob Jenkins' one-at-a-time hash */
static uint32_t static uint32_t
oaathash_update(register uint32_t h, register const uint8_t *cp, oaathash_update(register uint32_t h, register const uint8_t *cp,
register size_t n) register size_t n)
@ -996,33 +993,43 @@ oaathash_update(register uint32_t h, register const uint8_t *cp,
return (h); return (h);
} }
void static uint32_t
change_random(const void *vp, size_t n) oaathash_finalise(register uint32_t h)
{ {
register uint32_t h = 0x100;
struct {
const void *sp, *bp, *dp;
size_t dsz;
struct timeval tv;
uint32_t s;
} i;
i.dp = vp;
i.dsz = n;
i.s = lcg_state;
i.bp = &lcg_state;
i.sp = &i;
gettimeofday(&i.tv, NULL);
h = oaathash_update(oaathash_update(h, (void *)&i, sizeof(i)), vp, n);
/* oaathash_finalise */
h += h << 3; h += h << 3;
h ^= h >> 11; h ^= h >> 11;
h += h << 15; h += h << 15;
lcg_state = h; return (h);
}
uint32_t
oaathash_full(register const uint8_t *bp)
{
register uint32_t h = 0;
register uint8_t c;
while ((c = *bp++)) {
h += c;
h += h << 10;
h ^= h >> 6;
}
return (oaathash_finalise(h));
}
void
change_random(const void *vp, size_t n)
{
register uint32_t h = 0x100;
kshstate_v.cr_dp = vp;
kshstate_v.cr_dsz = n;
gettimeofday(&kshstate_v.cr_tv, NULL);
h = oaathash_update(oaathash_update(h, (void *)&kshstate_v,
sizeof(kshstate_v)), vp, n);
kshstate_v.lcg_state_ = oaathash_finalise(h);
} }
#endif
/* /*
* handle special variables with side effects - PATH, SECONDS. * handle special variables with side effects - PATH, SECONDS.
@ -1074,15 +1081,12 @@ getspec(struct tbl *vp)
return; return;
break; break;
case V_RANDOM: case V_RANDOM:
#if HAVE_ARC4RANDOM
i = arc4random() & 0x7FFF;
#else
/* /*
* this is the same Linear Congruential PRNG as Borland * this is the same Linear Congruential PRNG as Borland
* C/C++ allegedly uses in its built-in rand() function * C/C++ allegedly uses in its built-in rand() function
*/ */
i = ((lcg_state = 22695477 * lcg_state + 1) >> 16) & 0x7FFF; i = ((kshstate_v.lcg_state_ =
#endif 22695477 * kshstate_v.lcg_state_ + 1) >> 16) & 0x7FFF;
break; break;
case V_HISTSIZE: case V_HISTSIZE:
i = histsize; i = histsize;
@ -1196,25 +1200,11 @@ setspec(struct tbl *vp)
x_lins = i; x_lins = i;
break; break;
case V_RANDOM: case V_RANDOM:
#if HAVE_ARC4RANDOM
#if HAVE_ARC4RANDOM_PUSHB
if (Flag(FARC4RANDOM))
/*
* things like initialisation, environment import,
* etc. are already done
*/
arc4random_pushb(&i, sizeof(i));
else
/* during start-up phase or somesuch */
#endif /* HAVE_ARC4RANDOM_PUSHB */
arc4random_addrandom((void *)&i, sizeof(i));
#else /* !HAVE_ARC4RANDOM */
/* /*
* mksh R40+ no longer has the traditional repeatability * mksh R39d+ no longer has the traditional repeatability
* of $RANDOM sequences, but always retains state * of $RANDOM sequences, but always retains state
*/ */
change_random(&i, sizeof(i)); change_random(&i, sizeof(i));
#endif /* !HAVE_ARC4RANDOM */
break; break;
case V_SECONDS: case V_SECONDS:
{ {
@ -1259,13 +1249,12 @@ unsetspec(struct tbl *vp)
unspecial(vp->name); unspecial(vp->name);
break; break;
/* AT&T ksh man page says OPTIND, OPTARG and _ lose special meaning, /*
* but OPTARG does not (still set by getopts) and _ is also still * AT&T ksh man page says OPTIND, OPTARG and _ lose special
* set in various places. * meaning, but OPTARG does not (still set by getopts) and _ is
* Don't know what AT&T does for: * also still set in various places. Don't know what AT&T does
* HISTSIZE, HISTFILE, * for HISTSIZE, HISTFILE. Unsetting these in AT&T ksh does not
* Unsetting these in AT&T ksh does not loose the 'specialness': * loose the 'specialness': IFS, COLUMNS, PATH, TMPDIR
* no effect: IFS, COLUMNS, PATH, TMPDIR
*/ */
} }
} }
@ -1452,3 +1441,14 @@ change_winsz(void)
if (x_lins < MIN_LINS) if (x_lins < MIN_LINS)
x_lins = 24; x_lins = 24;
} }
uint32_t
evilhash(const char *s)
{
register uint32_t h = 0x100;
h = oaathash_update(h, (void *)&kshstate_f, sizeof(kshstate_f));
kshstate_f.h = oaathash_full((const uint8_t *)s);
return (oaathash_finalise(oaathash_update(h,
(void *)&kshstate_f.h, sizeof(kshstate_f.h))));
}