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
# $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
# 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
ac_cppflags ARC4RANDOM
ac_test arc4random_push arc4random 0 <<-'EOF'
extern void arc4random_push(int);
int main(void) { arc4random_push(1); return (0); }
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 (arc4random_pushb(*av, ac)); }
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 */
int main(void) { return (arc4random()); }
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
#include "sh.h"
void arc4random_push(long); /* this clashes if defined before */
int main(void) { arc4random_push(1); return (0); }
int arc4random_pushb(char, int); /* this clashes if defined before */
int main(int ac, char *av[]) { return (arc4random_pushb(**av, ac)); }
EOF
ac_test sys_siglist_decl sys_siglist 1 'if sys_siglist[] does not need to be declared' <<-'EOF'
#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
@ -17,12 +17,12 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 \
-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_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_MKNOD=1 -DHAVE_REVOKE=1 -DHAVE_SETMODE=1 \
-DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 -DHAVE_STRCASESTR=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
COPTS+= -std=gnu99 -Wall
.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: 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 $
@ -7,7 +7,7 @@
# http://www.research.att.com/~gsf/public/ifs.sh
expected-stdout:
@(#)MIRBSD KSH R30 2007/07/31
@(#)MIRBSD KSH R30 2007/08/12
description:
Check version of shell.
category: pdksh

7
jobs.c
View File

@ -2,7 +2,7 @@
#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! */
#define PRUNNING 0
@ -369,6 +369,9 @@ exchild(struct op *t, int flags,
else
p->pid = i;
/* Ensure next child gets a (slightly) different $RANDOM sequence */
change_random((p->pid << 1) | (ischild ? 1 : 0));
/* job control set up */
if (Flag(FMONITOR) && !(flags&XXCOM)) {
int dotty = 0;
@ -437,8 +440,6 @@ exchild(struct op *t, int flags,
}
/* shell (parent) stuff */
/* Ensure next child gets a (slightly) different $RANDOM sequence */
change_random();
if (!(flags & XPIPEO)) { /* last process in a job */
j_startjob(j);
if (flags & XCOPROC) {

7
main.c
View File

@ -13,7 +13,7 @@
#include <locale.h>
#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;
@ -222,8 +222,9 @@ main(int argc, const char *argv[])
setstr(pwd_v, current_wd, KSH_RETURN_ERROR);
}
ppid = getppid();
#if !HAVE_ARC4RANDOM
srand(((long)kshname) ^ ((long)time(NULL) * kshpid * ppid));
change_random(((u_long)kshname) ^ ((u_long)time(NULL) * kshpid * ppid));
#if HAVE_ARC4RANDOM
Flag(FARC4RANDOM) = 2; /* use arc4random(3) until $RANDOM is written */
#endif
setint(global("PPID"), (long)ppid);

7
misc.c
View File

@ -6,7 +6,7 @@
#include <grp.h>
#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);
#undef USE_CHVT
@ -104,6 +104,9 @@ const struct shoption options[] = {
* entries MUST match the order of sh_flag F* enumerations in sh.h.
*/
{ "allexport", 'a', OF_ANY },
#if HAVE_ARC4RANDOM
{ "arc4random", 0, OF_ANY },
#endif
{ "braceexpand", 0, OF_ANY }, /* non-standard */
{ "bgnice", 0, OF_ANY },
{ NULL, 'c', OF_CMDLINE },
@ -232,7 +235,7 @@ change_flag(enum sh_flag f,
char oldval;
oldval = Flag(f);
Flag(f) = newval;
Flag(f) = newval ? 1 : 0; /* needed for tristates */
if (f == FMONITOR) {
if (what != OF_CMDLINE && newval != oldval)
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 $
.\"
.Dd July 31, 2007
.Dd August 12, 2007
.Dt MKSH 1
.Os MirBSD
.Sh NAME
@ -1590,16 +1590,9 @@ if the shell doesn't know where it is.
Every time
.Ev RANDOM
is referenced, it is assigned a pseudo-random number first.
By default,
.Xr arc4random 3
is used to produce unsigned 15\-bit values (0\-32767)
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 .
See the description of
.Ic set -o Ic arc4random
below for details.
.It Ev REPLY
Default parameter for the
.Ic read
@ -3344,6 +3337,18 @@ during file name generation.
Print commands and parameter assignments when they are executed, preceded by
the value of
.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
Background jobs are run with lower priority.
.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: 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_VERSION "R30 2007/07/31"
#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/08/12"
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
@ -194,8 +194,8 @@ typedef int bool;
extern u_int32_t arc4random(void);
#endif
#if !HAVE_ARC4RANDOM_PUSH_DECL
extern void arc4random_push(int);
#if !HAVE_ARC4RANDOM_PUSHB_DECL
extern uint32_t arc4random_pushb(void *, size_t);
#endif
#if !HAVE_SETMODE
@ -393,6 +393,9 @@ extern const struct shoption options[];
*/
enum sh_flag {
FEXPORT = 0, /* -a: export all */
#if HAVE_ARC4RANDOM
FARC4RANDOM, /* use 0:rand(3) 1:arc4random(3) 2:switch on write */
#endif
FBRACEEXPAND, /* enable {} globbing */
FBGNICE, /* bgnice */
FCOMMAND, /* -c: (invocation) execute specified command */
@ -431,7 +434,7 @@ enum sh_flag {
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];
@ -1479,7 +1482,7 @@ const char *skip_wdvarname(const char *, int);
int is_wdvarname(const char *, int);
int is_wdvarassign(const char *);
char **makenv(void);
void change_random(void);
void change_random(uint64_t);
int array_ref_len(const char *);
char *arrayname(const char *);
void set_array(const char *, int, const char **);

108
var.c
View File

@ -2,7 +2,7 @@
#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
@ -23,6 +23,8 @@ static void getspec(struct tbl *);
static void setspec(struct tbl *);
static void unsetspec(struct tbl *);
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
@ -849,25 +851,96 @@ makenv(void)
}
/*
* Someone has set the srand() value, therefore from now on
* we return values from rand() instead of arc4random()
* Get us a random number, either from rand(3) or arc4random(3), with
* 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
static int use_rand = 0;
static uint64_t rnd_cache = 0;
static char rnd_lastflag = 2;
#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.
* Done to ensure children will not get the same random number sequence
* if the parent doesn't use $RANDOM.
*/
void
change_random(void)
change_random(uint64_t newval)
{
int rval = 0;
newval &= 0x00001FFFFFFFFFFF;
newval |= (uint64_t)rand() << 45;
#if HAVE_ARC4RANDOM
if (use_rand)
if (Flag(FARC4RANDOM)) {
rnd_cache ^= newval;
return;
}
#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;
case V_RANDOM:
vp->flag &= ~SPECIAL;
#if HAVE_ARC4RANDOM
if (!use_rand)
setint(vp, arc4random() & 0x7FFF);
else
#endif
setint(vp, rand() & 0x7FFF);
setint(vp, rnd_get());
vp->flag |= SPECIAL;
break;
case V_HISTSIZE:
@ -963,7 +1031,7 @@ setspec(struct tbl *vp)
break;
case V_OPTIND:
vp->flag &= ~SPECIAL;
getopts_reset((int) intval(vp));
getopts_reset((int)intval(vp));
vp->flag |= SPECIAL;
break;
case V_TMPDIR:
@ -985,7 +1053,7 @@ setspec(struct tbl *vp)
break;
case V_HISTSIZE:
vp->flag &= ~SPECIAL;
sethistsize((int) intval(vp));
sethistsize((int)intval(vp));
vp->flag |= SPECIAL;
break;
#if HAVE_PERSISTENT_HISTORY
@ -999,13 +1067,7 @@ setspec(struct tbl *vp)
break;
case V_RANDOM:
vp->flag &= ~SPECIAL;
srand((unsigned int)intval(vp));
#if HAVE_ARC4RANDOM
use_rand = 1;
#if HAVE_ARC4RANDOM_PUSH
arc4random_push((unsigned)vp ^ (unsigned)rand());
#endif
#endif
rnd_set(intval(vp));
vp->flag |= SPECIAL;
break;
case V_SECONDS:
@ -1026,7 +1088,7 @@ setspec(struct tbl *vp)
case V_LINENO:
vp->flag &= ~SPECIAL;
/* 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;
break;
}