add “set -o arc4random”, RTFM for details

This commit is contained in:
tg 2007-08-12 13:42:23 +00:00
parent cf2eb697e2
commit 499327f7b8
9 changed files with 140 additions and 61 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# $MirOS: src/bin/mksh/Build.sh,v 1.250 2007/07/31 11:11:23 tg Exp $ # $MirOS: src/bin/mksh/Build.sh,v 1.251 2007/08/12 13:42:19 tg Exp $
#- #-
# Environment used: CC CFLAGS CPPFLAGS LDFLAGS LIBS NOWARN NROFF TARGET_OS # Environment used: CC CFLAGS CPPFLAGS LDFLAGS LIBS NOWARN NROFF TARGET_OS
# CPPFLAGS recognised: MKSH_SMALL MKSH_ASSUME_UTF8 MKSH_NEED_MKNOD MKSH_NOPWNAM # CPPFLAGS recognised: MKSH_SMALL MKSH_ASSUME_UTF8 MKSH_NEED_MKNOD MKSH_NOPWNAM
@ -760,9 +760,13 @@ if test $HAVE_ARC4RANDOM = 0 && test -f "$srcdir/arc4random.c"; then
fi fi
ac_cppflags ARC4RANDOM ac_cppflags ARC4RANDOM
ac_test arc4random_push arc4random 0 <<-'EOF' ac_test arc4random_pushb arc4random 0 <<-'EOF'
extern void arc4random_push(int); #include <sys/types.h>
int main(void) { arc4random_push(1); return (0); } #if HAVE_STDINT_H
#include <stdint.h>
#endif
extern uint32_t arc4random_pushb(void *, size_t);
int main(int ac, char *av[]) { return (arc4random_pushb(*av, ac)); }
EOF EOF
ac_test flock_ex '' 'flock and mmap' <<-'EOF' ac_test flock_ex '' 'flock and mmap' <<-'EOF'
@ -853,11 +857,11 @@ ac_test '!' arc4random_decl arc4random 1 'if arc4random() does not need to be de
long arc4random(void); /* this clashes if defined before */ long arc4random(void); /* this clashes if defined before */
int main(void) { return (arc4random()); } int main(void) { return (arc4random()); }
EOF EOF
ac_test '!' arc4random_push_decl arc4random_push 1 'if arc4random_push() does not need to be declared' <<-'EOF' ac_test '!' arc4random_pushb_decl arc4random_pushb 1 'if arc4random_pushb() does not need to be declared' <<-'EOF'
#define MKSH_INCLUDES_ONLY #define MKSH_INCLUDES_ONLY
#include "sh.h" #include "sh.h"
void arc4random_push(long); /* this clashes if defined before */ int arc4random_pushb(char, int); /* this clashes if defined before */
int main(void) { arc4random_push(1); return (0); } int main(int ac, char *av[]) { return (arc4random_pushb(**av, ac)); }
EOF EOF
ac_test sys_siglist_decl sys_siglist 1 'if sys_siglist[] does not need to be declared' <<-'EOF' ac_test sys_siglist_decl sys_siglist 1 'if sys_siglist[] does not need to be declared' <<-'EOF'
#define MKSH_INCLUDES_ONLY #define MKSH_INCLUDES_ONLY

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/Makefile,v 1.45 2007/07/31 11:11:23 tg Exp $ # $MirOS: src/bin/mksh/Makefile,v 1.46 2007/08/12 13:42:20 tg Exp $
#- #-
# use CPPFLAGS=-DDEBUG __CRAZY=Yes to check for certain more stuff # use CPPFLAGS=-DDEBUG __CRAZY=Yes to check for certain more stuff
@ -17,12 +17,12 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 \
-DHAVE_GRP_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 \ -DHAVE_GRP_H=1 -DHAVE_ULIMIT_H=0 -DHAVE_VALUES_H=0 \
-DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_SIGNAME=1 \ -DHAVE_RLIM_T=1 -DHAVE_SIG_T=1 -DHAVE_SYS_SIGNAME=1 \
-DHAVE_SYS_SIGLIST=1 -DHAVE_STRSIGNAL=0 -DHAVE_ARC4RANDOM=1 \ -DHAVE_SYS_SIGLIST=1 -DHAVE_STRSIGNAL=0 -DHAVE_ARC4RANDOM=1 \
-DHAVE_ARC4RANDOM_PUSH=1 -DHAVE_FLOCK_EX=1 \ -DHAVE_ARC4RANDOM_PUSHB=1 -DHAVE_FLOCK_EX=1 \
-DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 \ -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 \
-DHAVE_MKNOD=1 -DHAVE_REVOKE=1 -DHAVE_SETMODE=1 \ -DHAVE_MKNOD=1 -DHAVE_REVOKE=1 -DHAVE_SETMODE=1 \
-DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRCASESTR=1 \ -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRCASESTR=1 \
-DHAVE_STRLCPY=1 -DHAVE_ARC4RANDOM_DECL=1 \ -DHAVE_STRLCPY=1 -DHAVE_ARC4RANDOM_DECL=1 \
-DHAVE_ARC4RANDOM_PUSH_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \ -DHAVE_ARC4RANDOM_PUSHB_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \
-DHAVE_PERSISTENT_HISTORY=1 -DHAVE_PERSISTENT_HISTORY=1
COPTS+= -std=gnu99 -Wall COPTS+= -std=gnu99 -Wall
.endif .endif

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.132 2007/07/31 11:11:23 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.133 2007/08/12 13:42:20 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -7,7 +7,7 @@
# http://www.research.att.com/~gsf/public/ifs.sh # http://www.research.att.com/~gsf/public/ifs.sh
expected-stdout: expected-stdout:
@(#)MIRBSD KSH R30 2007/07/31 @(#)MIRBSD KSH R30 2007/08/12
description: description:
Check version of shell. Check version of shell.
category: pdksh category: pdksh

7
jobs.c
View File

@ -2,7 +2,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.25 2007/07/22 13:34:50 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.26 2007/08/12 13:42:21 tg Exp $");
/* Order important! */ /* Order important! */
#define PRUNNING 0 #define PRUNNING 0
@ -369,6 +369,9 @@ exchild(struct op *t, int flags,
else else
p->pid = i; p->pid = i;
/* Ensure next child gets a (slightly) different $RANDOM sequence */
change_random((p->pid << 1) | (ischild ? 1 : 0));
/* job control set up */ /* job control set up */
if (Flag(FMONITOR) && !(flags&XXCOM)) { if (Flag(FMONITOR) && !(flags&XXCOM)) {
int dotty = 0; int dotty = 0;
@ -437,8 +440,6 @@ exchild(struct op *t, int flags,
} }
/* shell (parent) stuff */ /* shell (parent) stuff */
/* Ensure next child gets a (slightly) different $RANDOM sequence */
change_random();
if (!(flags & XPIPEO)) { /* last process in a job */ if (!(flags & XPIPEO)) { /* last process in a job */
j_startjob(j); j_startjob(j);
if (flags & XCOPROC) { if (flags & XCOPROC) {

7
main.c
View File

@ -13,7 +13,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.84 2007/07/22 13:34:51 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/main.c,v 1.85 2007/08/12 13:42:21 tg Exp $");
extern char **environ; extern char **environ;
@ -222,8 +222,9 @@ main(int argc, const char *argv[])
setstr(pwd_v, current_wd, KSH_RETURN_ERROR); setstr(pwd_v, current_wd, KSH_RETURN_ERROR);
} }
ppid = getppid(); ppid = getppid();
#if !HAVE_ARC4RANDOM change_random(((u_long)kshname) ^ ((u_long)time(NULL) * kshpid * ppid));
srand(((long)kshname) ^ ((long)time(NULL) * kshpid * ppid)); #if HAVE_ARC4RANDOM
Flag(FARC4RANDOM) = 2; /* use arc4random(3) until $RANDOM is written */
#endif #endif
setint(global("PPID"), (long)ppid); setint(global("PPID"), (long)ppid);

7
misc.c
View File

@ -6,7 +6,7 @@
#include <grp.h> #include <grp.h>
#endif #endif
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.64 2007/07/26 13:23:51 tg Exp $\t" __RCSID("$MirOS: src/bin/mksh/misc.c,v 1.65 2007/08/12 13:42:21 tg Exp $\t"
MKSH_SH_H_ID); MKSH_SH_H_ID);
#undef USE_CHVT #undef USE_CHVT
@ -104,6 +104,9 @@ const struct shoption options[] = {
* entries MUST match the order of sh_flag F* enumerations in sh.h. * entries MUST match the order of sh_flag F* enumerations in sh.h.
*/ */
{ "allexport", 'a', OF_ANY }, { "allexport", 'a', OF_ANY },
#if HAVE_ARC4RANDOM
{ "arc4random", 0, OF_ANY },
#endif
{ "braceexpand", 0, OF_ANY }, /* non-standard */ { "braceexpand", 0, OF_ANY }, /* non-standard */
{ "bgnice", 0, OF_ANY }, { "bgnice", 0, OF_ANY },
{ NULL, 'c', OF_CMDLINE }, { NULL, 'c', OF_CMDLINE },
@ -232,7 +235,7 @@ change_flag(enum sh_flag f,
char oldval; char oldval;
oldval = Flag(f); oldval = Flag(f);
Flag(f) = newval; Flag(f) = newval ? 1 : 0; /* needed for tristates */
if (f == FMONITOR) { if (f == FMONITOR) {
if (what != OF_CMDLINE && newval != oldval) if (what != OF_CMDLINE && newval != oldval)
j_change(); j_change();

29
mksh.1
View File

@ -1,7 +1,7 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.93 2007/07/31 15:29:40 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.94 2007/08/12 13:42:22 tg Exp $
.\" $OpenBSD: ksh.1,v 1.120 2007/05/31 20:47:44 otto Exp $ .\" $OpenBSD: ksh.1,v 1.120 2007/05/31 20:47:44 otto Exp $
.\" .\"
.Dd July 31, 2007 .Dd August 12, 2007
.Dt MKSH 1 .Dt MKSH 1
.Os MirBSD .Os MirBSD
.Sh NAME .Sh NAME
@ -1590,16 +1590,9 @@ if the shell doesn't know where it is.
Every time Every time
.Ev RANDOM .Ev RANDOM
is referenced, it is assigned a pseudo-random number first. is referenced, it is assigned a pseudo-random number first.
By default, See the description of
.Xr arc4random 3 .Ic set -o Ic arc4random
is used to produce unsigned 15\-bit values (0\-32767) below for details.
whose quality depends on the operating environment.
If
.Ev RANDOM
is assigned a value, it is used as the seed to
.Xr srand 3
and subsequent references yield a semi-predictable sequence from
.Xr rand 3 .
.It Ev REPLY .It Ev REPLY
Default parameter for the Default parameter for the
.Ic read .Ic read
@ -3344,6 +3337,18 @@ 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
Use
.Xr arc4random 3
high-quality random numbers for the value of
.Ev RANDOM
if set (to either 1 or 2), or a semi-predictable sequence from
.Xr rand 3
if unset.
Setting this flag will change its value to 1; the default value is 2,
which means it automatically switches to 0 if
.Ev RANDOM
is written to.
.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

15
sh.h
View File

@ -8,8 +8,8 @@
/* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */ /* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */
/* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */ /* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */
#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.167 2007/08/06 12:02:39 tg Exp $" #define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.168 2007/08/12 13:42:23 tg Exp $"
#define MKSH_VERSION "R30 2007/07/31" #define MKSH_VERSION "R30 2007/08/12"
#if HAVE_SYS_PARAM_H #if HAVE_SYS_PARAM_H
#include <sys/param.h> #include <sys/param.h>
@ -194,8 +194,8 @@ typedef int bool;
extern u_int32_t arc4random(void); extern u_int32_t arc4random(void);
#endif #endif
#if !HAVE_ARC4RANDOM_PUSH_DECL #if !HAVE_ARC4RANDOM_PUSHB_DECL
extern void arc4random_push(int); extern uint32_t arc4random_pushb(void *, size_t);
#endif #endif
#if !HAVE_SETMODE #if !HAVE_SETMODE
@ -393,6 +393,9 @@ extern const struct shoption options[];
*/ */
enum sh_flag { enum sh_flag {
FEXPORT = 0, /* -a: export all */ FEXPORT = 0, /* -a: export all */
#if HAVE_ARC4RANDOM
FARC4RANDOM, /* use 0:rand(3) 1:arc4random(3) 2:switch on write */
#endif
FBRACEEXPAND, /* enable {} globbing */ FBRACEEXPAND, /* enable {} globbing */
FBGNICE, /* bgnice */ FBGNICE, /* bgnice */
FCOMMAND, /* -c: (invocation) execute specified command */ FCOMMAND, /* -c: (invocation) execute specified command */
@ -431,7 +434,7 @@ enum sh_flag {
FNFLAGS /* (place holder: how many flags are there) */ FNFLAGS /* (place holder: how many flags are there) */
}; };
#define Flag(f) (shell_flags[(int) (f)]) #define Flag(f) (shell_flags[(int)(f)])
EXTERN char shell_flags[FNFLAGS]; EXTERN char shell_flags[FNFLAGS];
@ -1479,7 +1482,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);
void change_random(void); void change_random(uint64_t);
int array_ref_len(const char *); int array_ref_len(const char *);
char *arrayname(const char *); char *arrayname(const char *);
void set_array(const char *, int, const char **); void set_array(const char *, int, const char **);

108
var.c
View File

@ -2,7 +2,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.42 2007/07/22 14:01:50 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/var.c,v 1.43 2007/08/12 13:42:23 tg Exp $");
/* /*
* Variables * Variables
@ -23,6 +23,8 @@ static void getspec(struct tbl *);
static void setspec(struct tbl *); static void setspec(struct tbl *);
static void unsetspec(struct tbl *); static void unsetspec(struct tbl *);
static struct tbl *arraysearch(struct tbl *, int); static struct tbl *arraysearch(struct tbl *, int);
static int rnd_get(void);
static void rnd_set(long);
/* /*
* create a new block for function calls and simple commands * create a new block for function calls and simple commands
@ -849,25 +851,96 @@ makenv(void)
} }
/* /*
* Someone has set the srand() value, therefore from now on * Get us a random number, either from rand(3) or arc4random(3), with
* we return values from rand() instead of arc4random() * the latter being preferred. If Flag(FARC4RANDOM) is 0, we use rand(3),
* otherwise arc4random(3). We have static caches to make change_random
* and writes to $RANDOM a cheap operation.
*/ */
#if HAVE_ARC4RANDOM #if HAVE_ARC4RANDOM
static int use_rand = 0; static uint64_t rnd_cache = 0;
static char rnd_lastflag = 2;
#endif #endif
static int
rnd_get(void)
{
#if HAVE_ARC4RANDOM
#if HAVE_ARC4RANDOM_PUSHB
uint32_t rv = 0;
#endif
if (Flag(FARC4RANDOM) != rnd_lastflag) {
if (Flag(FARC4RANDOM) == 0) {
/* transition to 0 by set: srand */
srand(arc4random() & 0x7FFF);
} else if (rnd_lastflag == 0) {
/* transition from 0: addrandom */
rnd_cache ^= rand();
}
rnd_lastflag = Flag(FARC4RANDOM);
}
if (Flag(FARC4RANDOM)) {
if (rnd_cache)
#if HAVE_ARC4RANDOM_PUSHB
rv = arc4random_pushb(&rnd_cache, sizeof (rnd_cache));
#else
arc4random_addrandom(&rnd_cache, sizeof (rnd_cache));
#endif
rnd_cache = 0;
return ((
#if HAVE_ARC4RANDOM_PUSHB
rv ? rv :
#endif
arc4random()) & 0x7FFF);
}
#endif
return (rand() & 0x7FFF);
}
static void
rnd_set(long newval)
{
#if HAVE_ARC4RANDOM
rnd_cache ^= (((uint64_t)newval) << 15) | rand();
if (Flag(FARC4RANDOM) == 1)
return;
if (Flag(FARC4RANDOM) == 2)
Flag(FARC4RANDOM) = 0;
/* transition to 0 by write: only srand */
rnd_lastflag = 0;
#endif
srand(newval & 0x7FFF);
}
/* /*
* Called after a fork in parent to bump the random number generator. * Called after a fork in parent to bump the random number generator.
* Done to ensure children will not get the same random number sequence * Done to ensure children will not get the same random number sequence
* if the parent doesn't use $RANDOM. * if the parent doesn't use $RANDOM.
*/ */
void void
change_random(void) change_random(uint64_t newval)
{ {
int rval = 0;
newval &= 0x00001FFFFFFFFFFF;
newval |= (uint64_t)rand() << 45;
#if HAVE_ARC4RANDOM #if HAVE_ARC4RANDOM
if (use_rand) if (Flag(FARC4RANDOM)) {
rnd_cache ^= newval;
return;
}
#endif #endif
rand();
rval += newval & 0x7FFF;
newval >>= 15;
rval += newval & 0x7FFF;
newval >>= 15;
rval += newval & 0x7FFF;
newval >>= 15;
rval += newval;
rval = (rval & 0x7FFF) ^ (rval >> 15);
srand(rval);
} }
/* /*
@ -918,12 +991,7 @@ getspec(struct tbl *vp)
break; break;
case V_RANDOM: case V_RANDOM:
vp->flag &= ~SPECIAL; vp->flag &= ~SPECIAL;
#if HAVE_ARC4RANDOM setint(vp, rnd_get());
if (!use_rand)
setint(vp, arc4random() & 0x7FFF);
else
#endif
setint(vp, rand() & 0x7FFF);
vp->flag |= SPECIAL; vp->flag |= SPECIAL;
break; break;
case V_HISTSIZE: case V_HISTSIZE:
@ -963,7 +1031,7 @@ setspec(struct tbl *vp)
break; break;
case V_OPTIND: case V_OPTIND:
vp->flag &= ~SPECIAL; vp->flag &= ~SPECIAL;
getopts_reset((int) intval(vp)); getopts_reset((int)intval(vp));
vp->flag |= SPECIAL; vp->flag |= SPECIAL;
break; break;
case V_TMPDIR: case V_TMPDIR:
@ -985,7 +1053,7 @@ setspec(struct tbl *vp)
break; break;
case V_HISTSIZE: case V_HISTSIZE:
vp->flag &= ~SPECIAL; vp->flag &= ~SPECIAL;
sethistsize((int) intval(vp)); sethistsize((int)intval(vp));
vp->flag |= SPECIAL; vp->flag |= SPECIAL;
break; break;
#if HAVE_PERSISTENT_HISTORY #if HAVE_PERSISTENT_HISTORY
@ -999,13 +1067,7 @@ setspec(struct tbl *vp)
break; break;
case V_RANDOM: case V_RANDOM:
vp->flag &= ~SPECIAL; vp->flag &= ~SPECIAL;
srand((unsigned int)intval(vp)); rnd_set(intval(vp));
#if HAVE_ARC4RANDOM
use_rand = 1;
#if HAVE_ARC4RANDOM_PUSH
arc4random_push((unsigned)vp ^ (unsigned)rand());
#endif
#endif
vp->flag |= SPECIAL; vp->flag |= SPECIAL;
break; break;
case V_SECONDS: case V_SECONDS:
@ -1026,7 +1088,7 @@ setspec(struct tbl *vp)
case V_LINENO: case V_LINENO:
vp->flag &= ~SPECIAL; vp->flag &= ~SPECIAL;
/* The -1 is because line numbering starts at 1. */ /* The -1 is because line numbering starts at 1. */
user_lineno = (unsigned int) intval(vp) - current_lineno - 1; user_lineno = (unsigned int)intval(vp) - current_lineno - 1;
vp->flag |= SPECIAL; vp->flag |= SPECIAL;
break; break;
} }