diff options
author | Robert Mustacchi <rm@joyent.com> | 2014-12-26 02:46:52 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2015-02-15 00:36:58 +0000 |
commit | f31c6fa33bcc9a608ce6f9ffd671ffc2b65a30ef (patch) | |
tree | 804c1aad78118d760e083f79a0f411894272488f | |
parent | d34c3434a6ead24ec3e41daebf60ff85376c9e47 (diff) | |
download | illumos-joyent-f31c6fa33bcc9a608ce6f9ffd671ffc2b65a30ef.tar.gz |
OS-3845 want arc4random(3C) suite
OS-3846 want getentropy(3C)
OS-3847 want getrandom(2)
OS-3848 want explicit_bzero(3C)
OS-3843 want MC_INHERIT_ZERO
OS-3844 uuid_generate can leak its cache in edge conditions
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Joshua M. Clulow <josh@sysmgr.org>
82 files changed, 2884 insertions, 274 deletions
diff --git a/exception_lists/cstyle b/exception_lists/cstyle index d254ff5f15..67bbe870f0 100644 --- a/exception_lists/cstyle +++ b/exception_lists/cstyle @@ -123,8 +123,10 @@ usr/src/common/bzip2/bzlib.c usr/src/common/bzip2/decompress.c usr/src/common/bzip2/bzlib_private.h usr/src/common/bzip2/huffman.c +usr/src/common/crypto/chacha/chacha.c usr/src/common/openssl/crypto/krb5/krb5_asn.c usr/src/common/openssl/crypto/krb5/krb5_asn.h +usr/src/lib/libc/port/gen/arc4random_uniform.c usr/src/lib/gss_mechs/mech_krb5/crypto/aes/aes_s2k.c usr/src/lib/gss_mechs/mech_krb5/crypto/cksumtype_to_string.c usr/src/lib/gss_mechs/mech_krb5/crypto/coll_proof_cksum.c diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c index f6e4fd0bb8..423a658507 100644 --- a/usr/src/cmd/truss/print.c +++ b/usr/src/cmd/truss/print.c @@ -21,7 +21,7 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -83,6 +83,7 @@ #include <sys/rctl_impl.h> #include <sys/fork.h> #include <sys/task.h> +#include <sys/random.h> #include "ramdata.h" #include "print.h" #include "proto.h" @@ -2750,6 +2751,27 @@ prt_snf(private_t *pri, int raw, long val) prt_hex(pri, 0, val); } +void +prt_grf(private_t *pri, int raw, long val) +{ + int first = 1; + + if (raw != 0 || val == 0 || + (val & ~(GRND_NONBLOCK | GRND_RANDOM)) != 0) { + outstring(pri, "0"); + return; + } + + if (val & GRND_NONBLOCK) { + outstring(pri, "|GRND_NONBLOCK" + first); + first = 0; + } + if (val & GRND_RANDOM) { + outstring(pri, "|GRND_RANDOM" + first); + first = 0; + } +} + /* * Array of pointers to print functions, one for each format. */ @@ -2855,5 +2877,6 @@ void (* const Print[])() = { prt_skc, /* SKC -- print sockconfig() subcode */ prt_acf, /* ACF -- print accept4 flags */ prt_pfd, /* PFD -- print pipe fds */ + prt_grf, /* GRF -- print getrandom flags */ prt_dec, /* HID -- hidden argument, make this the last one */ }; diff --git a/usr/src/cmd/truss/print.h b/usr/src/cmd/truss/print.h index 9a9a43b4cb..8725d2ca85 100644 --- a/usr/src/cmd/truss/print.h +++ b/usr/src/cmd/truss/print.h @@ -21,6 +21,7 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -139,7 +140,8 @@ extern "C" { #define SKC 98 /* print sockconfig subcode */ #define ACF 99 /* accept4 flags */ #define PFD 100 /* pipe fds[2] */ -#define HID 101 /* hidden argument, don't print */ +#define GRF 101 /* getrandom flags */ +#define HID 102 /* hidden argument, don't print */ /* make sure HID is always the last member */ /* diff --git a/usr/src/cmd/truss/systable.c b/usr/src/cmd/truss/systable.c index 6035e8bcc6..8c736a7044 100644 --- a/usr/src/cmd/truss/systable.c +++ b/usr/src/cmd/truss/systable.c @@ -348,7 +348,7 @@ const struct systable systable[] = { {"preadv", 4, DEC, NOV, DEC, HEX, DEC, DEC}, /* 123 */ {"pwritev", 4, DEC, NOV, DEC, HEX, DEC, DEC}, /* 124 */ { NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX}, -{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX}, +{"getrandom", 3, DEC, NOV, IOB, UNS, GRF}, /* 126 */ {"mmapobj", 5, DEC, NOV, DEC, MOB, HEX, HEX, HEX}, /* 127 */ {"setrlimit", 2, DEC, NOV, RLM, HEX}, /* 128 */ {"getrlimit", 2, DEC, NOV, RLM, HEX}, /* 129 */ diff --git a/usr/src/common/crypto/chacha/chacha.c b/usr/src/common/crypto/chacha/chacha.c new file mode 100644 index 0000000000..5f9ef3b411 --- /dev/null +++ b/usr/src/common/crypto/chacha/chacha.c @@ -0,0 +1,221 @@ +/* +chacha-merged.c version 20080118 +D. J. Bernstein +Public domain. +*/ + +/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */ + +#include <chacha.h> +#include <stddef.h> + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned int u_int; + +#define U8C(v) (v##U) +#define U32C(v) (v##U) + +#define U8V(v) ((u8)(v) & U8C(0xFF)) +#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) + +#define ROTL32(v, n) \ + (U32V((v) << (n)) | ((v) >> (32 - (n)))) + +#define U8TO32_LITTLE(p) \ + (((u32)((p)[0]) ) | \ + ((u32)((p)[1]) << 8) | \ + ((u32)((p)[2]) << 16) | \ + ((u32)((p)[3]) << 24)) + +#define U32TO8_LITTLE(p, v) \ + do { \ + (p)[0] = U8V((v) ); \ + (p)[1] = U8V((v) >> 8); \ + (p)[2] = U8V((v) >> 16); \ + (p)[3] = U8V((v) >> 24); \ + } while (0) + +#define ROTATE(v,c) (ROTL32(v,c)) +#define XOR(v,w) ((v) ^ (w)) +#define PLUS(v,w) (U32V((v) + (w))) +#define PLUSONE(v) (PLUS((v),1)) + +#define QUARTERROUND(a,b,c,d) \ + a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ + c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ + a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ + c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); + +static const char sigma[16] = "expand 32-byte k"; +static const char tau[16] = "expand 16-byte k"; + +void +chacha_keysetup(chacha_ctx_t *x,const u8 *k,u32 kbits,u32 ivbits) +{ + const char *constants; + + x->chacha_input[4] = U8TO32_LITTLE(k + 0); + x->chacha_input[5] = U8TO32_LITTLE(k + 4); + x->chacha_input[6] = U8TO32_LITTLE(k + 8); + x->chacha_input[7] = U8TO32_LITTLE(k + 12); + if (kbits == 256) { /* recommended */ + k += 16; + constants = sigma; + } else { /* kbits == 128 */ + constants = tau; + } + x->chacha_input[8] = U8TO32_LITTLE(k + 0); + x->chacha_input[9] = U8TO32_LITTLE(k + 4); + x->chacha_input[10] = U8TO32_LITTLE(k + 8); + x->chacha_input[11] = U8TO32_LITTLE(k + 12); + x->chacha_input[0] = U8TO32_LITTLE(constants + 0); + x->chacha_input[1] = U8TO32_LITTLE(constants + 4); + x->chacha_input[2] = U8TO32_LITTLE(constants + 8); + x->chacha_input[3] = U8TO32_LITTLE(constants + 12); +} + +void +chacha_ivsetup(chacha_ctx_t *x,const u8 *iv) +{ + x->chacha_input[12] = 0; + x->chacha_input[13] = 0; + x->chacha_input[14] = U8TO32_LITTLE(iv + 0); + x->chacha_input[15] = U8TO32_LITTLE(iv + 4); +} + +void +chacha_encrypt_bytes(chacha_ctx_t *x,const u8 *m,u8 *c,u32 bytes) +{ + u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + u8 *ctarget = NULL; + u8 tmp[64]; + u_int i; + + if (!bytes) return; + + j0 = x->chacha_input[0]; + j1 = x->chacha_input[1]; + j2 = x->chacha_input[2]; + j3 = x->chacha_input[3]; + j4 = x->chacha_input[4]; + j5 = x->chacha_input[5]; + j6 = x->chacha_input[6]; + j7 = x->chacha_input[7]; + j8 = x->chacha_input[8]; + j9 = x->chacha_input[9]; + j10 = x->chacha_input[10]; + j11 = x->chacha_input[11]; + j12 = x->chacha_input[12]; + j13 = x->chacha_input[13]; + j14 = x->chacha_input[14]; + j15 = x->chacha_input[15]; + + for (;;) { + if (bytes < 64) { + for (i = 0;i < bytes;++i) tmp[i] = m[i]; + m = tmp; + ctarget = c; + c = tmp; + } + x0 = j0; + x1 = j1; + x2 = j2; + x3 = j3; + x4 = j4; + x5 = j5; + x6 = j6; + x7 = j7; + x8 = j8; + x9 = j9; + x10 = j10; + x11 = j11; + x12 = j12; + x13 = j13; + x14 = j14; + x15 = j15; + for (i = 20;i > 0;i -= 2) { + QUARTERROUND( x0, x4, x8,x12) + QUARTERROUND( x1, x5, x9,x13) + QUARTERROUND( x2, x6,x10,x14) + QUARTERROUND( x3, x7,x11,x15) + QUARTERROUND( x0, x5,x10,x15) + QUARTERROUND( x1, x6,x11,x12) + QUARTERROUND( x2, x7, x8,x13) + QUARTERROUND( x3, x4, x9,x14) + } + x0 = PLUS(x0,j0); + x1 = PLUS(x1,j1); + x2 = PLUS(x2,j2); + x3 = PLUS(x3,j3); + x4 = PLUS(x4,j4); + x5 = PLUS(x5,j5); + x6 = PLUS(x6,j6); + x7 = PLUS(x7,j7); + x8 = PLUS(x8,j8); + x9 = PLUS(x9,j9); + x10 = PLUS(x10,j10); + x11 = PLUS(x11,j11); + x12 = PLUS(x12,j12); + x13 = PLUS(x13,j13); + x14 = PLUS(x14,j14); + x15 = PLUS(x15,j15); + +#ifndef KEYSTREAM_ONLY + x0 = XOR(x0,U8TO32_LITTLE(m + 0)); + x1 = XOR(x1,U8TO32_LITTLE(m + 4)); + x2 = XOR(x2,U8TO32_LITTLE(m + 8)); + x3 = XOR(x3,U8TO32_LITTLE(m + 12)); + x4 = XOR(x4,U8TO32_LITTLE(m + 16)); + x5 = XOR(x5,U8TO32_LITTLE(m + 20)); + x6 = XOR(x6,U8TO32_LITTLE(m + 24)); + x7 = XOR(x7,U8TO32_LITTLE(m + 28)); + x8 = XOR(x8,U8TO32_LITTLE(m + 32)); + x9 = XOR(x9,U8TO32_LITTLE(m + 36)); + x10 = XOR(x10,U8TO32_LITTLE(m + 40)); + x11 = XOR(x11,U8TO32_LITTLE(m + 44)); + x12 = XOR(x12,U8TO32_LITTLE(m + 48)); + x13 = XOR(x13,U8TO32_LITTLE(m + 52)); + x14 = XOR(x14,U8TO32_LITTLE(m + 56)); + x15 = XOR(x15,U8TO32_LITTLE(m + 60)); +#endif + + j12 = PLUSONE(j12); + if (!j12) { + j13 = PLUSONE(j13); + /* stopping at 2^70 bytes per nonce is user's responsibility */ + } + + U32TO8_LITTLE(c + 0,x0); + U32TO8_LITTLE(c + 4,x1); + U32TO8_LITTLE(c + 8,x2); + U32TO8_LITTLE(c + 12,x3); + U32TO8_LITTLE(c + 16,x4); + U32TO8_LITTLE(c + 20,x5); + U32TO8_LITTLE(c + 24,x6); + U32TO8_LITTLE(c + 28,x7); + U32TO8_LITTLE(c + 32,x8); + U32TO8_LITTLE(c + 36,x9); + U32TO8_LITTLE(c + 40,x10); + U32TO8_LITTLE(c + 44,x11); + U32TO8_LITTLE(c + 48,x12); + U32TO8_LITTLE(c + 52,x13); + U32TO8_LITTLE(c + 56,x14); + U32TO8_LITTLE(c + 60,x15); + + if (bytes <= 64) { + if (bytes < 64) { + for (i = 0;i < bytes;++i) ctarget[i] = c[i]; + } + x->chacha_input[12] = j12; + x->chacha_input[13] = j13; + return; + } + bytes -= 64; + c += 64; +#ifndef KEYSTREAM_ONLY + m += 64; +#endif + } +} diff --git a/usr/src/common/crypto/chacha/chacha.h b/usr/src/common/crypto/chacha/chacha.h new file mode 100644 index 0000000000..ac9993a8a4 --- /dev/null +++ b/usr/src/common/crypto/chacha/chacha.h @@ -0,0 +1,50 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +#ifndef _CHACHA_H +#define _CHACHA_H + +/* + * ChaCha cipher implementation header + * + * Note, the chacha C files that we have, have a compile time option for + * generating a keystream only. eg. in other words -DKEYSTREAM_ONLY. If using + * chacha, for something like arc4random, where you aren't doing encryption, + * then you should pass -DKEYSTREAM_ONLY. If encryption is being done, then it + * should not be defined. The main difference is basically doing another pass + * over the data and xoring it with the generated cipher. + */ + +#include <inttypes.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct chacha_ctx { + uint32_t chacha_input[16]; +} chacha_ctx_t; + +extern void chacha_keysetup(chacha_ctx_t *, const uint8_t *, uint32_t, + uint32_t); +extern void chacha_ivsetup(chacha_ctx_t *, const uint8_t *); +extern void chacha_encrypt_bytes(chacha_ctx_t *, const uint8_t *, uint8_t *, + uint32_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _CHACHA_H */ diff --git a/usr/src/head/stdlib.h b/usr/src/head/stdlib.h index 4aaee3ca30..a9b55e5acb 100644 --- a/usr/src/head/stdlib.h +++ b/usr/src/head/stdlib.h @@ -260,6 +260,17 @@ extern char *ulltostr(unsigned long long, char *); #endif /* defined(__EXTENSIONS__) || !defined(_STRICT_STDC) ... */ +/* OpenBSD compatibility functions */ +#if !defined(_STRICT_SYMBOLS) + +#include <inttypes.h> +extern uint32_t arc4random(void); +extern void arc4random_buf(void *, size_t); +extern uint32_t arc4random_uniform(uint32_t); + +#endif /* !_STRICT_SYBMOLS */ + + #ifdef __cplusplus } #endif diff --git a/usr/src/head/string.h b/usr/src/head/string.h index 8ef411a60b..6801c7eb9d 100644 --- a/usr/src/head/string.h +++ b/usr/src/head/string.h @@ -109,6 +109,7 @@ extern int strncasecmp_l(const char *, const char *, size_t, locale_t); #if !defined(_STRICT_SYMBOLS) /* Note that some of these are also declared in strings.h for XPG4_2+ */ +extern void explicit_bzero(void *, size_t); extern int uucopy(const void *_RESTRICT_KYWD, void *_RESTRICT_KYWD, size_t); extern int uucopystr(const void *_RESTRICT_KYWD, void *_RESTRICT_KYWD, size_t); extern int ffs(int); diff --git a/usr/src/head/unistd.h b/usr/src/head/unistd.h index 826c777ba8..685d1ab4fc 100644 --- a/usr/src/head/unistd.h +++ b/usr/src/head/unistd.h @@ -717,6 +717,10 @@ extern char *ttyname_r(int, char *, int); #endif /* defined(__EXTENSIONS__) || defined(_REENTRANT)... */ +#if !defined(_STRICT_SYMBOLS) +extern int getentropy(void *, size_t); +#endif /* !_STRICT_SYMBOLS */ + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libc/Makefile.targ b/usr/src/lib/libc/Makefile.targ index cb01074143..2322885346 100644 --- a/usr/src/lib/libc/Makefile.targ +++ b/usr/src/lib/libc/Makefile.targ @@ -288,6 +288,11 @@ $(UNICODEOBJS:%=pics/%): $(SRC)/common/unicode/$$(@F:.o=.c) $(COMPILE.c) -o $@ $(SRC)/common/unicode/$(@F:.o=.c) $(POST_PROCESS_O) +$(CHACHAOBJS:%=pics/%): $(SRC)/common/crypto/chacha/$$(@F:.o=.c) + $(COMPILE.c) -I$(SRC)/common/crypto/chacha -DKEYSTREAM_ONLY \ + -o $@ $(SRC)/common/crypto/chacha/$(@F:.o=.c) + $(POST_PROCESS_O) + # DTrace rules pics/%.o: $(LIBCBASE)/../port/threads/%.d $(THREADSOBJS:%=pics/%) $(COMPILE.d) -C -xlazyload -s $< -o $@ $(THREADSOBJS:%=pics/%) diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile index d9f4e5ddc2..0627569c46 100644 --- a/usr/src/lib/libc/amd64/Makefile +++ b/usr/src/lib/libc/amd64/Makefile @@ -89,6 +89,9 @@ FPASMOBJS= \ ATOMICOBJS= \ atomic.o +CHACHAOBJS= \ + chacha.o + XATTROBJS= \ xattr_common.o COMOBJS= \ @@ -106,6 +109,8 @@ GENOBJS= \ _getsp.o \ abs.o \ alloca.o \ + arc4random.o \ + arc4random_uniform.o \ attrat.o \ byteorder.o \ cuexit.o \ @@ -202,6 +207,7 @@ COMSYSOBJS= \ getpid.o \ getpmsg.o \ getppid.o \ + getrandom.o \ getrlimit.o \ getuid.o \ gtty.o \ @@ -374,6 +380,7 @@ PORTGEN= \ euclen.o \ event_port.o \ execvp.o \ + explicit_bzero.o \ fattach.o \ fdetach.o \ fdopendir.o \ @@ -388,6 +395,7 @@ PORTGEN= \ getcwd.o \ getdate_err.o \ getdtblsize.o \ + getentropy.o \ getenv.o \ getexecname.o \ getgrnam.o \ @@ -925,6 +933,7 @@ MOSTOBJS= \ $(I386FPOBJS) \ $(FPASMOBJS) \ $(ATOMICOBJS) \ + $(CHACHAOBJS) \ $(XATTROBJS) \ $(COMOBJS) \ $(GENOBJS) \ @@ -1167,6 +1176,8 @@ $(PORTSTDIO_C89:%=pics/%) := \ $(PORTI18N_COND:%=pics/%) := \ CPPFLAGS += -D_WCS_LONGLONG +pics/arc4random.o := CPPFLAGS += -I$(SRC)/common/crypto/chacha + .KEEP_STATE: all: $(LIBS) $(LIB_PIC) diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com index 0c7b9b2c1b..418c469019 100644 --- a/usr/src/lib/libc/i386/Makefile.com +++ b/usr/src/lib/libc/i386/Makefile.com @@ -89,6 +89,9 @@ FPASMOBJS= \ ATOMICOBJS= \ atomic.o +CHACHAOBJS= \ + chacha.o + XATTROBJS= \ xattr_common.o @@ -113,6 +116,8 @@ GENOBJS= \ _mul64.o \ abs.o \ alloca.o \ + arc4random.o \ + arc4random_uniform.o \ byteorder.o \ byteorder64.o \ cuexit.o \ @@ -226,6 +231,7 @@ COMSYSOBJS= \ getpid.o \ getpmsg.o \ getppid.o \ + getrandom.o \ getrlimit.o \ getuid.o \ gtty.o \ @@ -407,6 +413,7 @@ PORTGEN= \ euclen.o \ event_port.o \ execvp.o \ + explicit_bzero.o \ fattach.o \ fdetach.o \ fdopendir.o \ @@ -421,6 +428,7 @@ PORTGEN= \ getcwd.o \ getdate_err.o \ getdtblsize.o \ + getentropy.o \ getenv.o \ getexecname.o \ getgrnam.o \ @@ -961,6 +969,7 @@ MOSTOBJS= \ $(FPOBJS) \ $(FPASMOBJS) \ $(ATOMICOBJS) \ + $(CHACHAOBJS) \ $(XATTROBJS) \ $(COMOBJS) \ $(DTRACEOBJS) \ @@ -1228,6 +1237,8 @@ $(PORTSTDIO_C89:%=pics/%) := \ $(PORTI18N_COND:%=pics/%) := \ CPPFLAGS += -D_WCS_LONGLONG +pics/arc4random.o := CPPFLAGS += -I$(SRC)/common/crypto/chacha + .KEEP_STATE: all: $(LIBS) $(LIB_PIC) diff --git a/usr/src/lib/libc/port/gen/arc4random.c b/usr/src/lib/libc/port/gen/arc4random.c new file mode 100644 index 0000000000..d82f12bd2a --- /dev/null +++ b/usr/src/lib/libc/port/gen/arc4random.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 1996, David Mazieres <dm@uun.org> + * Copyright (c) 2008, Damien Miller <djm@openbsd.org> + * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> + * Copyright (c) 2015 Joyent, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * arc4random(3C), derived from the OpenBSD version. + * + * To ensure that a parent process and any potential children see a different + * state, we mmap the entire arc4_state_t structure and mark that page as + * MC_INHERIT_ZERO. That ensures that the data is zeroed, and really the bit we + * care about, arc4_init is set to B_FALSE, which will cause the child to + * reinitialize it when they first use the interface. + */ + +#include <synch.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/sysmacros.h> +#include <chacha.h> + +#include "thr_uberdata.h" + +#define ARC4_KEYSZ 32 +#define ARC4_IVSZ 8 +#define ARC4_BLOCKSZ 64 +#define ARC4_KSBUFSZ (16*ARC4_BLOCKSZ) /* key stream byte size */ +#define ARC4_COUNT 1600000 /* bytes for rekeying */ + +typedef struct arc4_state { + boolean_t arc4_init; /* Initialized? */ + size_t arc4_have; /* Valid bytes in arc4_buf */ + size_t arc4_count; /* bytes until reseed */ + chacha_ctx_t arc4_chacha; /* chacha context */ + uint8_t arc4_buf[ARC4_KSBUFSZ]; /* keystream blocks */ +} arc4_state_t; + +static arc4_state_t *arc4; +static mutex_t arc4_lock = DEFAULTMUTEX; + +static void +arc4_init(uint8_t *buf, size_t n) +{ + if (n < ARC4_KEYSZ + ARC4_IVSZ) + abort(); + + chacha_keysetup(&arc4->arc4_chacha, buf, ARC4_KEYSZ * 8, 0); + chacha_ivsetup(&arc4->arc4_chacha, buf + ARC4_KEYSZ); +} + +static void +arc4_rekey(uint8_t *data, size_t datalen) +{ + /* Fill in the keystream buffer */ + chacha_encrypt_bytes(&arc4->arc4_chacha, arc4->arc4_buf, arc4->arc4_buf, + sizeof (arc4->arc4_buf)); + + /* mix in optional user provided data */ + if (data != NULL) { + size_t i, m; + + m = MIN(datalen, ARC4_KEYSZ + ARC4_IVSZ); + for (i = 0; i < m; i++) + arc4->arc4_buf[i] ^= data[i]; + } + + /* immediately reinit for backtracking resistence */ + arc4_init(arc4->arc4_buf, ARC4_KEYSZ + ARC4_IVSZ); + explicit_bzero(arc4->arc4_buf, ARC4_KEYSZ + ARC4_IVSZ); + arc4->arc4_have = sizeof (arc4->arc4_buf) - ARC4_KEYSZ - ARC4_IVSZ; +} + +static void +arc4_stir(size_t len) +{ + uint8_t rnd[ARC4_KEYSZ + ARC4_IVSZ]; + + if (arc4->arc4_count <= len) { + if (getentropy(rnd, sizeof (rnd)) == -1) + abort(); + + if (arc4->arc4_init == B_FALSE) { + arc4_init(rnd, sizeof (rnd)); + arc4->arc4_init = B_TRUE; + } else { + arc4_rekey(rnd, sizeof (rnd)); + } + explicit_bzero(rnd, sizeof (rnd)); + + /* Invalidate the data buffer */ + arc4->arc4_have = 0; + memset(arc4->arc4_buf, 0, sizeof (arc4->arc4_buf)); + arc4->arc4_count = ARC4_COUNT; + } + + if (arc4->arc4_count <= len) { + arc4->arc4_count = 0; + } else { + arc4->arc4_count -= len; + } +} + +static void +arc4_fill(uint8_t *buf, size_t n) +{ + if (arc4 == NULL) { + size_t pgsz, mapsz; + void *a; + + pgsz = sysconf(_SC_PAGESIZE); + if (pgsz == -1) + abort(); + mapsz = P2ROUNDUP(sizeof (arc4_state_t), pgsz); + a = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (a == MAP_FAILED) + abort(); + if (memcntl(a, mapsz, MC_INHERIT_ZERO, 0, 0, 0) != 0) + abort(); + arc4 = a; + } + + arc4_stir(n); + while (n > 0) { + if (arc4->arc4_have > 0) { + uint8_t *keystream; + size_t m = MIN(n, arc4->arc4_have); + + keystream = arc4->arc4_buf + sizeof (arc4->arc4_buf) - + arc4->arc4_have; + memcpy(buf, keystream, m); + explicit_bzero(keystream, m); + buf += m; + n -= m; + arc4->arc4_have -= m; + } + if (arc4->arc4_have == 0) + arc4_rekey(NULL, 0); + } +} + +uint32_t +arc4random(void) +{ + uint32_t out; + + lmutex_lock(&arc4_lock); + arc4_fill((uint8_t *)&out, sizeof (uint32_t)); + lmutex_unlock(&arc4_lock); + return (out); +} + +void +arc4random_buf(void *buf, size_t n) +{ + lmutex_lock(&arc4_lock); + arc4_fill(buf, n); + lmutex_unlock(&arc4_lock); +} diff --git a/usr/src/lib/libc/port/gen/arc4random_uniform.c b/usr/src/lib/libc/port/gen/arc4random_uniform.c new file mode 100644 index 0000000000..1aa9a622f1 --- /dev/null +++ b/usr/src/lib/libc/port/gen/arc4random_uniform.c @@ -0,0 +1,56 @@ +/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */ + +/* + * Copyright (c) 2008, Damien Miller <djm@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <stdlib.h> + +/* + * Calculate a uniformly distributed random number less than upper_bound + * avoiding "modulo bias". + * + * Uniformity is achieved by generating new random numbers until the one + * returned is outside the range [0, 2**32 % upper_bound). This + * guarantees the selected random number will be inside + * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) + * after reduction modulo upper_bound. + */ +uint32_t +arc4random_uniform(uint32_t upper_bound) +{ + uint32_t r, min; + + if (upper_bound < 2) + return 0; + + /* 2**32 % x == (2**32 - x) % x */ + min = -upper_bound % upper_bound; + + /* + * This could theoretically loop forever but each retry has + * p > 0.5 (worst case, usually far better) of selecting a + * number inside the range we need, so it should rarely need + * to re-roll. + */ + for (;;) { + r = arc4random(); + if (r >= min) + break; + } + + return r % upper_bound; +} diff --git a/usr/src/lib/libc/port/gen/explicit_bzero.c b/usr/src/lib/libc/port/gen/explicit_bzero.c new file mode 100644 index 0000000000..b27b4b9866 --- /dev/null +++ b/usr/src/lib/libc/port/gen/explicit_bzero.c @@ -0,0 +1,21 @@ +/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */ +/* + * Public domain. + * Written by Matthew Dempsky. + */ + +#include <string.h> + +#pragma weak __explicit_bzero_hook +/* ARGSUSED */ +void +__explicit_bzero_hook(void *buf, size_t len) +{ +} + +void +explicit_bzero(void *buf, size_t len) +{ + (void) memset(buf, 0, len); + __explicit_bzero_hook(buf, len); +} diff --git a/usr/src/lib/libc/port/gen/getentropy.c b/usr/src/lib/libc/port/gen/getentropy.c new file mode 100644 index 0000000000..4392727a95 --- /dev/null +++ b/usr/src/lib/libc/port/gen/getentropy.c @@ -0,0 +1,41 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * getentropy(3C) is an OpenBSD compatible wrapper around getrandom(2). + */ + +#include <errno.h> +#include <sys/random.h> + +int +getentropy(void *buf, size_t buflen) +{ + int ret; + + if (buflen > 256) { + errno = EIO; + return (-1); + } + + ret = getrandom(buf, buflen, 0); + if (ret == -1 || ret != buflen) { + if (errno != EFAULT) + errno = EIO; + return (-1); + } + + return (0); +} diff --git a/usr/src/lib/libc/port/gen/sh_locks.c b/usr/src/lib/libc/port/gen/sh_locks.c index 6583efbc9c..cf879195c6 100644 --- a/usr/src/lib/libc/port/gen/sh_locks.c +++ b/usr/src/lib/libc/port/gen/sh_locks.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "lint.h" #include <mtlib.h> #include <sys/types.h> diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers index 68eedf25b0..ed666e9b4d 100644 --- a/usr/src/lib/libc/port/mapfile-vers +++ b/usr/src/lib/libc/port/mapfile-vers @@ -2861,6 +2861,7 @@ $endif _getfp; _getgroupsbymember; _getlogin_r; + getrandom; _getsp; __gettsp; getvmusage; @@ -3176,6 +3177,17 @@ $if i386 __udivrem64; $endif +# +# The following functions should become public symbols when they get +# upstreamed to illumos and become part of their own appropriate symbol +# version. +# + arc4random; + arc4random_buf; + arc4random_uniform; + explicit_bzero; + getentropy; + # The following functions should not be exported from libc, # but /lib/libm.so.2, some older versions of the Studio # compiler/debugger components, and some ancient programs diff --git a/usr/src/lib/libc/port/sys/getrandom.c b/usr/src/lib/libc/port/sys/getrandom.c new file mode 100644 index 0000000000..8e59f526a1 --- /dev/null +++ b/usr/src/lib/libc/port/sys/getrandom.c @@ -0,0 +1,24 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015 Joyent, Inc. + */ + +#include <sys/types.h> +#include <sys/syscall.h> +#include <sys/random.h> + +int +getrandom(void *buf, size_t len, int flags) +{ + return (syscall(SYS_getrandom, buf, len, flags)); +} diff --git a/usr/src/lib/libc/sparc/Makefile.com b/usr/src/lib/libc/sparc/Makefile.com index 71867bf07d..bcd4b79c8b 100644 --- a/usr/src/lib/libc/sparc/Makefile.com +++ b/usr/src/lib/libc/sparc/Makefile.com @@ -115,6 +115,9 @@ $(__GNUC)FPASMOBJS += \ ATOMICOBJS= \ atomic.o +CHACHAOBJS= \ + chacha.o + XATTROBJS= \ xattr_common.o @@ -138,6 +141,8 @@ GENOBJS= \ _xregs_clrptr.o \ abs.o \ alloca.o \ + arc4random.o \ + arc4random_uniform.o \ ascii_strcasecmp.o \ byteorder.o \ cuexit.o \ @@ -246,6 +251,7 @@ COMSYSOBJS= \ getpid.o \ getpmsg.o \ getppid.o \ + getrandom.o \ getrlimit.o \ getuid.o \ gtty.o \ @@ -438,6 +444,7 @@ PORTGEN= \ euclen.o \ event_port.o \ execvp.o \ + explicit_bzero.o \ fattach.o \ fdetach.o \ fdopendir.o \ @@ -452,6 +459,7 @@ PORTGEN= \ getcwd.o \ getdate_err.o \ getdtblsize.o \ + getentropy.o \ getenv.o \ getexecname.o \ getgrnam.o \ @@ -997,6 +1005,7 @@ MOSTOBJS= \ $(FPOBJS) \ $(FPASMOBJS) \ $(ATOMICOBJS) \ + $(CHACHAOBJS) \ $(XATTROBJS) \ $(COMOBJS) \ $(DTRACEOBJS) \ @@ -1293,6 +1302,8 @@ $(PORTSTDIO_C89:%=pics/%) := \ $(PORTI18N_COND:%=pics/%) := \ CPPFLAGS += -D_WCS_LONGLONG +pics/arc4random.o := CPPFLAGS += -I$(SRC)/common/crypto/chacha + # Files which need extra optimization pics/getenv.o := sparc_COPTFLAG = -xO4 diff --git a/usr/src/lib/libc/sparcv9/Makefile.com b/usr/src/lib/libc/sparcv9/Makefile.com index f6628f8899..87fa17b911 100644 --- a/usr/src/lib/libc/sparcv9/Makefile.com +++ b/usr/src/lib/libc/sparcv9/Makefile.com @@ -117,6 +117,9 @@ $(__GNUC)FPASMOBJS += \ ATOMICOBJS= \ atomic.o +CHACHAOBJS= \ + chacha.o + XATTROBJS= \ xattr_common.o @@ -137,6 +140,8 @@ GENOBJS= \ _xregs_clrptr.o \ abs.o \ alloca.o \ + arc4random.o \ + arc4random_uniform.o \ ascii_strcasecmp.o \ byteorder.o \ cuexit.o \ @@ -229,6 +234,7 @@ COMSYSOBJS= \ getpid.o \ getpmsg.o \ getppid.o \ + getrandom.o \ getrlimit.o \ getuid.o \ gtty.o \ @@ -398,6 +404,7 @@ PORTGEN= \ euclen.o \ event_port.o \ execvp.o \ + explicit_bzero.o \ fattach.o \ fdetach.o \ fdopendir.o \ @@ -412,6 +419,7 @@ PORTGEN= \ getcwd.o \ getdate_err.o \ getdtblsize.o \ + getentropy.o \ getenv.o \ getexecname.o \ getgrnam.o \ @@ -940,6 +948,7 @@ MOSTOBJS= \ $(FPOBJS64) \ $(FPASMOBJS) \ $(ATOMICOBJS) \ + $(CHACHAOBJS) \ $(XATTROBJS) \ $(COMOBJS) \ $(GENOBJS) \ @@ -1216,6 +1225,8 @@ $(PORTPRINT_W:%=pics/%) := \ $(PORTI18N_COND:%=pics/%) := \ CPPFLAGS += -D_WCS_LONGLONG +pics/arc4random.o := CPPFLAGS += -I$(SRC)/common/crypto/chacha + # Files which need extra optimization pics/getenv.o := sparcv9_COPTFLAG = -xO4 diff --git a/usr/src/lib/libproc/common/proc_names.c b/usr/src/lib/libproc/common/proc_names.c index b0a4dfa131..634a79b312 100644 --- a/usr/src/lib/libproc/common/proc_names.c +++ b/usr/src/lib/libproc/common/proc_names.c @@ -239,7 +239,7 @@ static const char *const systable[] = { "preadv", /* 123 */ "pwritev", /* 124 */ NULL, /* 125 */ - NULL, /* 126 */ + "getrandom", /* 126 */ "mmapobj", /* 127 */ "setrlimit", /* 128 */ "getrlimit", /* 129 */ diff --git a/usr/src/lib/libuuid/common/uuid.c b/usr/src/lib/libuuid/common/uuid.c index 287fbba55c..481f11082a 100644 --- a/usr/src/lib/libuuid/common/uuid.c +++ b/usr/src/lib/libuuid/common/uuid.c @@ -22,7 +22,7 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Milan Jurik. All rights reserved. - * Copyright 2014 Joyent, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. All rights reserved. * Copyright 2014 Andrew Stormont. */ @@ -77,16 +77,6 @@ static int file_type; static int fd; /* - * The urandmtx mutex prevents multiple opens of /dev/urandom and protects the - * cache. - */ -#define RCACHE_SIZE 65535 -static mutex_t urandmtx; -static int fd_urand = -1; -static char rcache[RCACHE_SIZE]; -static char *rcachep = rcache; - -/* * misc routines */ uint16_t get_random(void); @@ -102,7 +92,6 @@ int get_ethernet_address(uuid_node_t *); static int map_state(); static void format_uuid(struct uuid *, uint16_t, uuid_time_t, uuid_node_t); -static void fill_random_bytes(uchar_t *, int); static int uuid_create(struct uuid *); static void gen_ethernet_address(uuid_node_t *); static void revalidate_data(uuid_node_t *); @@ -196,7 +185,7 @@ gen_ethernet_address(uuid_node_t *system_node) uchar_t node[6]; if (get_ethernet_address(system_node) != 0) { - fill_random_bytes(node, 6); + arc4random_buf(node, 6); (void) memcpy(system_node->nodeID, node, 6); /* * use 8:0:20 with the multicast bit set @@ -324,111 +313,6 @@ uuid_print(struct uuid u) } /* - * Only called with urandmtx held. - * Fills/refills the cache of randomness. We know that our allocations of - * randomness are always much less than the total size of the cache. - * Tries to use /dev/urandom random number generator - if that fails for some - * reason, it retries MAX_RETRY times then sets rcachep to NULL so we no - * longer use the cache. - */ -static void -load_cache() -{ - int i, retries = 0; - int nbytes = RCACHE_SIZE; - char *buf = rcache; - - while (nbytes > 0) { - i = read(fd_urand, buf, nbytes); - if ((i < 0) && (errno == EINTR)) { - continue; - } - if (i <= 0) { - if (retries++ == MAX_RETRY) - break; - continue; - } - nbytes -= i; - buf += i; - retries = 0; - } - if (nbytes == 0) - rcachep = rcache; - else - rcachep = NULL; -} - -static void -close_pre() -{ - (void) mutex_lock(&urandmtx); -} - -static void -close_parent() -{ - (void) mutex_unlock(&urandmtx); -} - -static void -close_child() -{ - if (fd_urand != -1) { - (void) close(fd_urand); - fd_urand = -1; - } - (void) mutex_unlock(&urandmtx); -} - -#pragma init(cache_init) -static void -cache_init(void) -{ - (void) pthread_atfork(close_pre, close_parent, close_child); -} - -/* - * Fills buf with random numbers - nbytes is the number of bytes - * to fill-in. Tries to use cached data from the /dev/urandom random number - * generator - if that fails for some reason, it uses srand48(3C) - */ -static void -fill_random_bytes(uchar_t *buf, int nbytes) -{ - int i; - - if (fd_urand == -1) { - (void) mutex_lock(&urandmtx); - /* check again now that we have the mutex */ - if (fd_urand == -1) { - if ((fd_urand = open(URANDOM_PATH, - O_RDONLY | O_CLOEXEC)) >= 0) - load_cache(); - } - (void) mutex_unlock(&urandmtx); - } - if (fd_urand >= 0 && rcachep != NULL) { - int cnt; - - (void) mutex_lock(&urandmtx); - if (rcachep != NULL && - (rcachep + nbytes) >= (rcache + RCACHE_SIZE)) - load_cache(); - - if (rcachep != NULL) { - for (cnt = 0; cnt < nbytes; cnt++) - *buf++ = *rcachep++; - (void) mutex_unlock(&urandmtx); - return; - } - (void) mutex_unlock(&urandmtx); - } - for (i = 0; i < nbytes; i++) { - *buf++ = get_random() & 0xFF; - } -} - -/* * Unpacks the structure members in "struct uuid" to a char string "uuid_t". */ void @@ -514,7 +398,7 @@ uuid_generate_random(uuid_t uu) (void) memset(uu, 0, sizeof (uuid_t)); (void) memset(&uuid, 0, sizeof (struct uuid)); - fill_random_bytes(uu, sizeof (uuid_t)); + arc4random_buf(uu, sizeof (uuid_t)); string_to_struct(&uuid, uu); /* * This is version 4, so say so in the UUID version field (4 bits) @@ -560,30 +444,12 @@ uuid_generate_time(uuid_t uu) /* * Creates a new UUID. The uuid will be generated based on high-quality - * randomness from /dev/urandom, if available by calling uuid_generate_random. - * If it failed to generate UUID then uuid_generate will call - * uuid_generate_time. + * randomness from arc4random(3C). */ void uuid_generate(uuid_t uu) { - if (uu == NULL) { - return; - } - if (fd_urand == -1) { - (void) mutex_lock(&urandmtx); - /* check again now that we have the mutex */ - if (fd_urand == -1) { - if ((fd_urand = open(URANDOM_PATH, O_RDONLY)) >= 0) - load_cache(); - } - (void) mutex_unlock(&urandmtx); - } - if (fd_urand >= 0) { - uuid_generate_random(uu); - } else { - (void) uuid_generate_time(uu); - } + uuid_generate_random(uu); } /* diff --git a/usr/src/lib/libuuid/common/uuid_misc.c b/usr/src/lib/libuuid/common/uuid_misc.c index 547531c19e..a6c320c158 100644 --- a/usr/src/lib/libuuid/common/uuid_misc.c +++ b/usr/src/lib/libuuid/common/uuid_misc.c @@ -22,6 +22,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2015, Joyent, Inc. */ /* @@ -120,18 +121,7 @@ get_current_time(uuid_time_t *timestamp) uint16_t get_random(void) { - static int initted = 0; - uuid_time_t time_now; - long seed; - - if (!initted) { - get_system_time(&time_now); - time_now = time_now/UUIDS_PER_TOD_CALL; - seed = (unsigned)(((time_now >> 32) ^ time_now)&0xffffffff); - srand48(seed); - initted = 1; - } - return (mrand48()); + return (arc4random_uniform(UINT16_MAX)); } /* diff --git a/usr/src/man/man3c/Makefile b/usr/src/man/man3c/Makefile index 88e1741bc2..9e88c23bec 100644 --- a/usr/src/man/man3c/Makefile +++ b/usr/src/man/man3c/Makefile @@ -14,7 +14,7 @@ # Copyright 2013 Nexenta Systems, Inc. All rights reserved. # Copyright 2013, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2014 Garrett D'Amore <garrett@damore.org> -# Copyright (c) 2014, Joyent, Inc. All rights reserved. +# Copyright (c) 2015, Joyent, Inc. All rights reserved. # include $(SRC)/Makefile.master @@ -40,6 +40,7 @@ MANFILES= __fbufsize.3c \ aiocancel.3c \ aioread.3c \ aiowait.3c \ + arc4random.3c \ assert.3c \ atexit.3c \ atomic_add.3c \ @@ -155,6 +156,7 @@ MANFILES= __fbufsize.3c \ getcwd.3c \ getdate.3c \ getdtablesize.3c \ + getentropy.3c \ getenv.3c \ getexecname.3c \ getgrnam.3c \ @@ -567,6 +569,8 @@ MANLINKS= FD_CLR.3c \ atoi.3c \ atol.3c \ atoll.3c \ + arc4random_buf.3c \ + arc4random_uniform.3c \ atomic_add_16.3c \ atomic_add_16_nv.3c \ atomic_add_32.3c \ @@ -743,6 +747,7 @@ MANLINKS= FD_CLR.3c \ etext.3c \ euccol.3c \ eucscol.3c \ + explicit_bzero.3c \ extended_to_decimal.3c \ fconvert.3c \ fcvt.3c \ @@ -1354,6 +1359,9 @@ llabs.3c := LINKSRC = abs.3c aiowrite.3c := LINKSRC = aioread.3c +arc4random_buf.3c := LINKSRC = arc4random.3c +arc4random_uniform.3c := LINKSRC = arc4random.3c + atomic_add_16.3c := LINKSRC = atomic_add.3c atomic_add_16_nv.3c := LINKSRC = atomic_add.3c atomic_add_32.3c := LINKSRC = atomic_add.3c @@ -1470,6 +1478,7 @@ atomic_swap_ushort.3c := LINKSRC = atomic_swap.3c bcmp.3c := LINKSRC = bstring.3c bcopy.3c := LINKSRC = bstring.3c bzero.3c := LINKSRC = bstring.3c +explicit_bzero.3c := LINKSRC = bstring.3c btowc_l.3c := LINKSRC = btowc.3c diff --git a/usr/src/man/man3c/THIRDPARTYLICENSE.arc4random b/usr/src/man/man3c/THIRDPARTYLICENSE.arc4random new file mode 100644 index 0000000000..e220e853cd --- /dev/null +++ b/usr/src/man/man3c/THIRDPARTYLICENSE.arc4random @@ -0,0 +1,30 @@ +.\" $OpenBSD: arc4random.3,v 1.35 2014/11/25 16:45:24 millert Exp $ +.\" +.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Niels Provos. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" diff --git a/usr/src/man/man3c/THIRDPARTYLICENSE.arc4random.descrip b/usr/src/man/man3c/THIRDPARTYLICENSE.arc4random.descrip new file mode 100644 index 0000000000..067aa2c7ef --- /dev/null +++ b/usr/src/man/man3c/THIRDPARTYLICENSE.arc4random.descrip @@ -0,0 +1 @@ +ARC4RANDOM MANUAL PAGE diff --git a/usr/src/man/man3c/THIRDPARTYLICENSE.getentropy b/usr/src/man/man3c/THIRDPARTYLICENSE.getentropy new file mode 100644 index 0000000000..64bec32b8a --- /dev/null +++ b/usr/src/man/man3c/THIRDPARTYLICENSE.getentropy @@ -0,0 +1,16 @@ +.\" $OpenBSD: getentropy.2,v 1.7 2014/12/10 19:19:00 schwarze Exp $ +.\" +.\" Copyright (c) 2014 Theo de Raadt +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" diff --git a/usr/src/man/man3c/THIRDPARTYLICENSE.getentropy.descrip b/usr/src/man/man3c/THIRDPARTYLICENSE.getentropy.descrip new file mode 100644 index 0000000000..7eef632426 --- /dev/null +++ b/usr/src/man/man3c/THIRDPARTYLICENSE.getentropy.descrip @@ -0,0 +1 @@ +GETENTROPY MANUAL PAGE diff --git a/usr/src/man/man3c/arc4random.3c b/usr/src/man/man3c/arc4random.3c new file mode 100644 index 0000000000..317fd31769 --- /dev/null +++ b/usr/src/man/man3c/arc4random.3c @@ -0,0 +1,106 @@ +.\" $OpenBSD: arc4random.3,v 1.35 2014/11/25 16:45:24 millert Exp $ +.\" +.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Niels Provos. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" Manual page, using -mandoc macros +.\" +.Dd "Dec 31, 2014" +.Dt ARC4RANDOM 3C +.Os +.Sh NAME +.Nm arc4random , +.Nm arc4random_buf , +.Nm arc4random_uniform +.Nd random number generator +.Sh SYNOPSIS +.In stdlib.h +.Ft uint32_t +.Fn arc4random "void" +.Ft void +.Fn arc4random_buf "void *buf" "size_t nbytes" +.Ft uint32_t +.Fn arc4random_uniform "uint32_t upper_bound" +.Sh DESCRIPTION +This family of functions provides higher quality data than those +described in +.Xr rand 3C , +.Xr random 3C , +and +.Xr rand48 3C . +.Pp +Use of these functions is encouraged for almost all random number +consumption because the other interfaces are deficient in either +quality, portability, standardization, or availability. +These functions can be called in almost all coding environments, +including +.Xr pthreads 5 +and +.Xr chroot 2 . +.Pp +High quality 32-bit pseudo-random numbers are generated very quickly. +On each call, a cryptographic pseudo-random number generator is used +to generate a new result. +One data pool is used for all consumers in a process, so that consumption +under program flow can act as additional stirring. +The subsystem is re-seeded from the kernel random number subsystem using +.Xr getentropy 2 +on a regular basis, and also upon +.Xr fork 2 . +.Pp +The +.Fn arc4random +function returns a single 32-bit value. +.Pp +.Fn arc4random_buf +fills the region +.Fa buf +of length +.Fa nbytes +with random data. +.Pp +.Fn arc4random_uniform +will return a single 32-bit value, uniformly distributed but less than +.Fa upper_bound . +This is recommended over constructions like +.Dq Li arc4random() % upper_bound +as it avoids "modulo bias" when the upper bound is not a power of two. +In the worst case, this function may consume multiple iterations +to ensure uniformity; see the source code to understand the problem +and solution. +.Sh RETURN VALUES +These functions are always successful, and no return value is +reserved to indicate an error. +.Sh INTERFACE STABILITY +.Sy Committed +.Sh MT-LEVEL +.Sy MT-Safe +.Sh SEE ALSO +.Xr rand 3C , +.Xr rand48 3C , +.Xr random 3C diff --git a/usr/src/man/man3c/bstring.3c b/usr/src/man/man3c/bstring.3c index f65f221ac5..873c64fe80 100644 --- a/usr/src/man/man3c/bstring.3c +++ b/usr/src/man/man3c/bstring.3c @@ -1,11 +1,12 @@ '\" te .\" Copyright (c) 2002, Sun Microsystems, Inc. All Rights Reserved +.\" Copyright (c) 2015, Joyent, Inc. .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH BSTRING 3C "Apr 15, 2002" +.TH BSTRING 3C "Dec 31, 2014" .SH NAME -bstring, bcopy, bcmp, bzero \- memory operations +bstring, bcopy, bcmp, bzero, explicit_bzero \- memory operations .SH SYNOPSIS .LP .nf @@ -24,8 +25,12 @@ bstring, bcopy, bcmp, bzero \- memory operations \fBvoid\fR \fBbzero\fR(\fBvoid *\fR\fIs\fR, \fBsize_t\fR \fIn\fR); .fi +.LP +.nf +\fBvoid\fR \fBexplicit_bzero\fR(\fBvoid *\fR\fIs\fR, \fBsize_t\fR \fIn\fR); +.fi + .SH DESCRIPTION -.sp .LP The \fBbcopy()\fR, \fBbcmp()\fR, and \fBbzero()\fR functions operate as efficiently as possible on memory areas (arrays of bytes bounded by a count, @@ -46,13 +51,15 @@ always returns 0 when \fIn\fR is 0. .LP The \fBbzero()\fR function sets the first \fIn\fR bytes in memory area \fIs\fR to 0. -.SH WARNINGS .sp .LP -The \fBbcopy()\fR function takes parameters backwards from \fBmemcmp()\fR. See -\fBmemory\fR(3C). +The \fBexplicit_bzero()\fR function behaves the same as \fBbzero()\fR, except it +should not be removed by the compiler's optimization passes. +.SH WARNINGS +.LP +The \fBbcopy()\fR and \fBexplicit_bzero()\fR functions take parameters backwards +from \fBmemcmp()\fR. See \fBmemory\fR(3C). .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -64,12 +71,15 @@ c | c l | l . ATTRIBUTE TYPE ATTRIBUTE VALUE _ -Interface Stability Standard +Interface Stability See NOTES _ MT-Level MT-Safe .TE .SH SEE ALSO -.sp .LP \fBmemory\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) +.SH NOTES +.LP +\fBbcopy\fR(), \fBbcmp\fR(), and \fBbzero\fR() are \fBSTANDARD\fR. +\fBexplicit_bzero\fR() is \fBCOMMITTED\fR. diff --git a/usr/src/man/man3c/drand48.3c b/usr/src/man/man3c/drand48.3c index 36b820a864..92d303b1d4 100644 --- a/usr/src/man/man3c/drand48.3c +++ b/usr/src/man/man3c/drand48.3c @@ -4,7 +4,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH DRAND48 3C "Jul 24, 2002" +.TH DRAND48 3C "Feb 11, 2015" .SH NAME drand48, erand48, lrand48, nrand48, mrand48, jrand48, srand48, seed48, lcong48 \- generate uniformly distributed pseudo-random numbers @@ -57,7 +57,6 @@ drand48, erand48, lrand48, nrand48, mrand48, jrand48, srand48, seed48, lcong48 .fi .SH DESCRIPTION -.sp .LP This family of functions generates pseudo-random numbers using the well-known linear congruential algorithm and 48-bit integer arithmetic. @@ -150,9 +149,11 @@ the multiplier \fIa\fR, and \fIparam\fR[6] specifies the 16-bit addend \fIc\fR. After \fBlcong48()\fR has been called, a subsequent call to either \fBsrand48()\fR or \fBseed48()\fR will restore the ``standard'' multiplier and addend values, \fIa\fR and \fIc\fR, specified above. -.SH ATTRIBUTES .sp .LP +For a more powerful random number generator, see \fBarc4random\fR(3C). +.SH ATTRIBUTES +.LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -169,6 +170,5 @@ MT-Level Safe .TE .SH SEE ALSO -.sp .LP -\fBrand\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) +\fBarc4random\fR(3C), \fBrand\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) diff --git a/usr/src/man/man3c/getentropy.3c b/usr/src/man/man3c/getentropy.3c new file mode 100644 index 0000000000..c149521c73 --- /dev/null +++ b/usr/src/man/man3c/getentropy.3c @@ -0,0 +1,65 @@ +.\" $OpenBSD: getentropy.2,v 1.7 2014/12/10 19:19:00 schwarze Exp $ +.\" +.\" Copyright (c) 2014 Theo de Raadt +.\" Copyright (c) 2015 Joyent, Inc. +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd "Dec 31, 2014" +.Dt GETENTROPY 3C +.Os +.Sh NAME +.Nm getentropy +.Nd get entropy +.Sh SYNOPSIS +.Fd #include <unistd.h> +.Ft int +.Fn getentropy "void *buf" "size_t buflen" +.Sh DESCRIPTION +.Nm +fills a buffer with high-quality entropy, which can be used +as input for process-context pseudorandom generators like +.Xr arc4random 3C . +.Pp +The maximum buffer size permitted is 256 bytes. +If +.Va buflen +exceeds this, an error of +.Er EIO +will be indicated. +.Pp +.Nm +is not intended for regular code; please use the +.Xr arc4random 3C +family of functions instead. +.Sh RETURN VALUES +.Rv -std +.Sh ERRORS +.Fn getentropy +will succeed unless: +.Bl -tag -width Er +.It Er EFAULT +The +.Fa buf +parameter points to an +invalid address. +.It Er EIO +Too many bytes requested, or some other fatal error occurred. +.El +.Sh INTERFACE STABILITY +.Sy Comitted +.Sh MT-LEVEL +.Sy Async-Signal-Safe +.Sh SEE ALSO +.Xr arc4random 3C +.Xr attributes 5 diff --git a/usr/src/man/man3c/rand.3c b/usr/src/man/man3c/rand.3c index 4fc6754c3b..8d66a8d2df 100644 --- a/usr/src/man/man3c/rand.3c +++ b/usr/src/man/man3c/rand.3c @@ -3,7 +3,7 @@ .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH RAND 3C "May 19, 2004" +.TH RAND 3C "Feb 11, 2015" .SH NAME rand, srand, rand_r \- simple random-number generator .SH SYNOPSIS @@ -25,7 +25,6 @@ rand, srand, rand_r \- simple random-number generator .fi .SH DESCRIPTION -.sp .LP The \fBrand()\fR function uses a multiplicative congruential random-number generator with period 2^32 that returns successive pseudo-random numbers in the @@ -55,9 +54,8 @@ call \fBrand_r()\fR with a pointer to the same seed object. The \fBrand_r()\fR function allows a thread to generate a private pseudo-random stream by having the seed object be private to the thread. .SH USAGE -.sp .LP -The spectral properties of \fBrand()\fR are limited. The \fBdrand48\fR(3C) +The spectral properties of \fBrand()\fR are limited. The \fBarc4random\fR(3C) function provides a better, more elaborate random-number generator. .sp .LP @@ -65,7 +63,6 @@ When compiling multithreaded applications, the \fB_REENTRANT\fR flag must be defined on the compile line. This flag should be used only in multithreaded applications. .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -83,6 +80,5 @@ MT-Level Safe .TE .SH SEE ALSO -.sp .LP -\fBdrand48\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) +\fBarc4random\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) diff --git a/usr/src/man/man3c/random.3c b/usr/src/man/man3c/random.3c index 6381bb498d..88edfcabee 100644 --- a/usr/src/man/man3c/random.3c +++ b/usr/src/man/man3c/random.3c @@ -32,7 +32,6 @@ random, srandom, initstate, setstate \- pseudorandom number functions .fi .SH DESCRIPTION -.sp .LP The \fBrandom()\fR function uses a nonlinear additive feedback random-number generator employing a default state array size of 31 long integers to return @@ -100,9 +99,11 @@ state arrays. The array defined by the \fIstate\fR argument is used for further random-number generation until \fBinitstate()\fR is called or \fBsetstate()\fR is called again. The \fBsetstate()\fR function returns a pointer to the previous state array. -.SH RETURN VALUES .sp .LP +For a more powerful random number generator, see \fBarc4random\fR(3C). +.SH RETURN VALUES +.LP The \fBrandom()\fR function returns the generated pseudo-random number. .sp .LP @@ -112,11 +113,9 @@ The \fBsrandom()\fR function returns no value. Upon successful completion, \fBinitstate()\fR and \fBsetstate()\fR return a pointer to the previous state array. Otherwise, a null pointer is returned. .SH ERRORS -.sp .LP No errors are defined. .SH USAGE -.sp .LP After initialization, a state array can be restarted at a different point in one of two ways: @@ -175,7 +174,6 @@ main() { .in -2 .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -193,11 +191,10 @@ MT-Level See \fBNOTES\fR below. .TE .SH SEE ALSO -.sp .LP -\fBdrand48\fR(3C), \fBrand\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5) +\fBarc4random\fR(3C), \fBdrand48\fR(3C), \fBrand\fR(3C), \fBattributes\fR(5), +\fBstandards\fR(5) .SH NOTES -.sp .LP The \fBrandom()\fR and \fBsrandom()\fR functions are unsafe in multithreaded applications. @@ -210,5 +207,5 @@ For \fBinitstate()\fR and \fBsetstate()\fR, the \fIstate\fR argument must be aligned on an \fBint\fR boundary. .sp .LP -Newer and better performing random number generators such as \fBaddrans()\fR -and \fBlcrans()\fR are available with the SUNWspro package. +\fBarc4random\fR(3C) is a newer and better performing random number generator. +Use it instead. diff --git a/usr/src/pkg/manifests/system-library.man3c.inc b/usr/src/pkg/manifests/system-library.man3c.inc index 0440f9bc40..ee9934f801 100644 --- a/usr/src/pkg/manifests/system-library.man3c.inc +++ b/usr/src/pkg/manifests/system-library.man3c.inc @@ -36,6 +36,7 @@ file path=usr/share/man/man3c/aiocancel.3c file path=usr/share/man/man3c/aioread.3c file path=usr/share/man/man3c/aiowait.3c file path=usr/share/man/man3c/assert.3c +file path=usr/share/man/man3c/arc4random.3c file path=usr/share/man/man3c/atexit.3c file path=usr/share/man/man3c/atomic_add.3c file path=usr/share/man/man3c/atomic_and.3c @@ -146,6 +147,7 @@ file path=usr/share/man/man3c/getcpuid.3c file path=usr/share/man/man3c/getcwd.3c file path=usr/share/man/man3c/getdate.3c file path=usr/share/man/man3c/getdtablesize.3c +file path=usr/share/man/man3c/getentropy.3c file path=usr/share/man/man3c/getenv.3c file path=usr/share/man/man3c/getexecname.3c file path=usr/share/man/man3c/getgrnam.3c @@ -546,6 +548,8 @@ link path=usr/share/man/man3c/addrtosymstr.3c target=walkcontext.3c link path=usr/share/man/man3c/aiowrite.3c target=aioread.3c link path=usr/share/man/man3c/alloca.3c target=malloc.3c link path=usr/share/man/man3c/alphasort.3c target=scandir.3c +link path=usr/share/man/man3c/arc4random_buf.3c target=arc4random.3c +link path=usr/share/man/man3c/arc4random_uniform.3c target=arc4random.3c link path=usr/share/man/man3c/ascftime.3c target=strftime.3c link path=usr/share/man/man3c/asctime.3c target=ctime.3c link path=usr/share/man/man3c/asctime_r.3c target=ctime.3c @@ -733,6 +737,7 @@ link path=usr/share/man/man3c/errx.3c target=err.3c link path=usr/share/man/man3c/etext.3c target=end.3c link path=usr/share/man/man3c/euccol.3c target=euclen.3c link path=usr/share/man/man3c/eucscol.3c target=euclen.3c +link path=usr/share/man/man3c/explicit_bzero.3c target=bstring.3c link path=usr/share/man/man3c/extended_to_decimal.3c \ target=floating_to_decimal.3c link path=usr/share/man/man3c/fconvert.3c target=econvert.3c diff --git a/usr/src/pkg/manifests/system-library.mf b/usr/src/pkg/manifests/system-library.mf index 089d9bc75d..b9715719cd 100644 --- a/usr/src/pkg/manifests/system-library.mf +++ b/usr/src/pkg/manifests/system-library.mf @@ -588,6 +588,10 @@ license usr/src/lib/passwdutil/THIRDPARTYLICENSE \ license=usr/src/lib/passwdutil/THIRDPARTYLICENSE license usr/src/lib/pkcs11/pkcs11_tpm/THIRDPARTYLICENSE \ license=usr/src/lib/pkcs11/pkcs11_tpm/THIRDPARTYLICENSE +license usr/src/man/man3c/THIRDPARTYLICENSE.arc4random \ + license=usr/src/man/man3c/THIRDPARTYLICENSE.arc4random +license usr/src/man/man3c/THIRDPARTYLICENSE.getentropy \ + license=usr/src/man/man3c/THIRDPARTYLICENSE.getentropy license usr/src/uts/common/sys/THIRDPARTYLICENSE.unicode \ license=usr/src/uts/common/sys/THIRDPARTYLICENSE.unicode link path=lib/$(ARCH64)/libadm.so target=libadm.so.1 diff --git a/usr/src/pkg/manifests/system-test-libctest.mf b/usr/src/pkg/manifests/system-test-libctest.mf index b635e7c74b..be5f063f04 100644 --- a/usr/src/pkg/manifests/system-test-libctest.mf +++ b/usr/src/pkg/manifests/system-test-libctest.mf @@ -25,6 +25,7 @@ dir path=opt/libc-tests dir path=opt/libc-tests/bin dir path=opt/libc-tests/runfiles dir path=opt/libc-tests/tests +dir path=opt/libc-tests/tests/random file path=opt/libc-tests/README mode=0444 file path=opt/libc-tests/bin/libctest mode=0555 file path=opt/libc-tests/runfiles/default.run mode=0444 @@ -43,6 +44,25 @@ $(i386_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.amd64 mode=0555 $(i386_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.i386 mode=0555 $(sparc_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.sparc mode=0555 $(sparc_ONLY)file path=opt/libc-tests/tests/nl_langinfo_test.sparcv9 mode=0555 +file path=opt/libc-tests/tests/random/arc4key.ksh mode=0555 +file path=opt/libc-tests/tests/random/arc4random mode=0555 +file path=opt/libc-tests/tests/random/arc4random_fork mode=0555 +file path=opt/libc-tests/tests/random/arc4random_forkall mode=0555 +file path=opt/libc-tests/tests/random/arc4random_forksig mode=0555 +file path=opt/libc-tests/tests/random/arc4random_prefork mode=0555 +file path=opt/libc-tests/tests/random/arc4random_preforkall mode=0555 +file path=opt/libc-tests/tests/random/arc4random_preforksig mode=0555 +file path=opt/libc-tests/tests/random/arc4random_rekey mode=0555 +file path=opt/libc-tests/tests/random/chacha mode=0555 +file path=opt/libc-tests/tests/random/getentropy mode=0555 +file path=opt/libc-tests/tests/random/getrandom mode=0555 +file path=opt/libc-tests/tests/random/inz_child mode=0555 +file path=opt/libc-tests/tests/random/inz_inval mode=0555 +file path=opt/libc-tests/tests/random/inz_mlock mode=0555 +file path=opt/libc-tests/tests/random/inz_region mode=0555 +file path=opt/libc-tests/tests/random/inz_split mode=0555 +file path=opt/libc-tests/tests/random/inz_split_vpp mode=0555 +file path=opt/libc-tests/tests/random/inz_vpp mode=0555 file path=opt/libc-tests/tests/wcsrtombs_test mode=0555 $(i386_ONLY)file path=opt/libc-tests/tests/wcsrtombs_test.amd64 mode=0555 $(i386_ONLY)file path=opt/libc-tests/tests/wcsrtombs_test.i386 mode=0555 diff --git a/usr/src/test/libc-tests/runfiles/default.run b/usr/src/test/libc-tests/runfiles/default.run index deadcb8c1c..f9db51fa69 100644 --- a/usr/src/test/libc-tests/runfiles/default.run +++ b/usr/src/test/libc-tests/runfiles/default.run @@ -31,3 +31,22 @@ outputdir = /var/tmp/test_results [/opt/libc-tests/tests/wcsrtombs_test] [/opt/libc-tests/tests/wctype_test] + +[/opt/libc-tests/tests/random/getrandom] +[/opt/libc-tests/tests/random/getentropy] +[/opt/libc-tests/tests/random/chacha] +[/opt/libc-tests/tests/random/inz_child] +[/opt/libc-tests/tests/random/inz_inval] +[/opt/libc-tests/tests/random/inz_mlock] +[/opt/libc-tests/tests/random/inz_region] +[/opt/libc-tests/tests/random/inz_split] +[/opt/libc-tests/tests/random/inz_split_vpp] +[/opt/libc-tests/tests/random/inz_vpp] +[/opt/libc-tests/tests/random/arc4random] +[/opt/libc-tests/tests/random/arc4random_fork] +[/opt/libc-tests/tests/random/arc4random_prefork] +[/opt/libc-tests/tests/random/arc4random_forkall] +[/opt/libc-tests/tests/random/arc4random_preforkall] +[/opt/libc-tests/tests/random/arc4random_forksig] +[/opt/libc-tests/tests/random/arc4random_preforksig] +[/opt/libc-tests/tests/random/arc4key.ksh] diff --git a/usr/src/test/libc-tests/tests/Makefile b/usr/src/test/libc-tests/tests/Makefile index 0ce3902862..1e3f288b2e 100644 --- a/usr/src/test/libc-tests/tests/Makefile +++ b/usr/src/test/libc-tests/tests/Makefile @@ -14,7 +14,7 @@ # Copyright 2014 Garrett D'Amore <garrett@damore.org> # -SUBDIRS = fpround newlocale nl_langinfo wcsrtombs wctype +SUBDIRS = fpround newlocale nl_langinfo wcsrtombs wctype random include $(SRC)/Makefile.master include $(SRC)/test/Makefile.com diff --git a/usr/src/test/libc-tests/tests/random/Makefile b/usr/src/test/libc-tests/tests/random/Makefile new file mode 100644 index 0000000000..42281e024f --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/Makefile @@ -0,0 +1,94 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015 Joyent, Inc. +# + +include $(SRC)/Makefile.master + +ROOTOPTPKG = $(ROOT)/opt/libc-tests +TESTDIR = $(ROOTOPTPKG)/tests/random +ROOTBINDIR = $(ROOTOPTPKG)/bin + +PROGS = arc4random \ + arc4random_prefork \ + arc4random_fork \ + arc4random_preforkall \ + arc4random_forkall \ + arc4random_preforksig \ + arc4random_forksig \ + arc4random_rekey \ + chacha \ + getentropy \ + getrandom \ + inz_child \ + inz_inval \ + inz_mlock \ + inz_region \ + inz_split \ + inz_split_vpp \ + inz_vpp + +SCRIPTS = arc4key.ksh + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/test/Makefile.com + +CMDS = $(PROGS:%=$(TESTDIR)/%) $(SCRIPTS:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +all: $(PROGS) + +install: all $(CMDS) + +lint: + +clobber: clean + -$(RM) $(PROGS) + +clean: + -$(RM) *.o + +$(CMDS): $(TESTDIR) $(PROGS) + +arc4random_prefork: arc4random_fork.c + $(LINK.c) -o $@ -DARC4_PREINIT=1 arc4random_fork.c $(LDLIBS) + $(POST_PROCESS) + +arc4random_preforkall: arc4random_forkall.c + $(LINK.c) -o $@ -DARC4_PREINIT=1 arc4random_forkall.c $(LDLIBS) + $(POST_PROCESS) + +arc4random_preforksig: arc4random_forksig.c + $(LINK.c) -o $@ -DARC4_PREINIT=1 arc4random_forksig.c $(LDLIBS) + $(POST_PROCESS) + +chacha: chacha_tv.c + $(COMPILE.c) -DKEYSTREAM_ONLY -I$(SRC)/common/crypto/chacha -o chacha.o -c $(SRC)/common/crypto/chacha/chacha.c + $(COMPILE.c) -I$(SRC)/common/crypto/chacha -o chacha_tv.o -c chacha_tv.c + $(LINK.c) -o $@ chacha_tv.o chacha.o $(LDLIBS) + $(POST_PROCESS) + +$(ROOTBINDIR): + $(INS.dir) + +$(ROOTBINDIR)/%: % + $(INS.file) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/libc-tests/tests/random/arc4key.ksh b/usr/src/test/libc-tests/tests/random/arc4key.ksh new file mode 100644 index 0000000000..3060708d30 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/arc4key.ksh @@ -0,0 +1,37 @@ +#!/usr/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2015, Joyent, Inc. +# + +# +# The purpose of this test is to verify that we have actually gone +# through and called the rekey functions in the implementation of the +# arc4random code that we have. To do that, we look at the actual part +# of the code that does generation. In this case, the function +# arc4_rekey() which is a private function as part of libc. +# + +set -o errexit + +arc_pname=$(basename $0) +arc_root=$(dirname $0)/../.. +arc_bin=$arc_root/bin/arc4random_rekey +arc_tmpfile=/tmp/$arc_pname.$$ +arc_count= + +rm -f $arc_tmpfile +dtrace -n 'pid$target::arc4_rekey:entry{ @ = count(); }' -c $arc_bin \ + -o $arc_tmpfile +arc_count=$(cat $arc_tmpfile) +[[ $arc_count -gt 1 ]] diff --git a/usr/src/test/libc-tests/tests/random/arc4random.c b/usr/src/test/libc-tests/tests/random/arc4random.c new file mode 100644 index 0000000000..9b6b4e5277 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/arc4random.c @@ -0,0 +1,40 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Basic tests for the arc4random(3C) family of functions. They should always + * succeed, let's make sure these do. + */ + +#include <stdlib.h> +#include <assert.h> +#include <errno.h> + +int +main(void) +{ + uint32_t ret; + uint8_t buf[32]; + + (void) arc4random(); + ret = arc4random_uniform(100); + assert(ret < 100); + ret = arc4random_uniform(200); + assert(ret < 200); + + arc4random_buf(buf, sizeof (buf)); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/arc4random_fork.c b/usr/src/test/libc-tests/tests/random/arc4random_fork.c new file mode 100644 index 0000000000..88cd2adb41 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/arc4random_fork.c @@ -0,0 +1,82 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Tests to make sure that a parent and child do not get the same arc4random + * state across a fork. This source file is used to make two tests. One which + * initializes the data in advance, one of which does not. + */ + +#include <stdlib.h> +#include <sys/mman.h> +#include <assert.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/wait.h> + +typedef struct arc4_fork { + uint32_t af_parent; + uint32_t af_child; + uint8_t af_pbuf[4096]; + uint8_t af_cbuf[4096]; +} arc4_fork_t; + +arc4_fork_t *fork_data; + +int +main(void) +{ + int e, i; + pid_t p, child; + +#ifdef ARC4_PREINIT + (void) arc4random(); +#endif + + fork_data = (arc4_fork_t *)mmap(NULL, sizeof (arc4_fork_t), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + assert(fork_data != MAP_FAILED); + + p = fork(); + assert(p != -1); + if (p == 0) { + fork_data->af_child = arc4random(); + arc4random_buf(fork_data->af_cbuf, sizeof (fork_data->af_cbuf)); + exit(0); + } + + fork_data->af_parent = arc4random(); + arc4random_buf(fork_data->af_pbuf, sizeof (fork_data->af_pbuf)); + do { + child = wait(&e); + } while (child == -1 && errno == EINTR); + assert(child == p); + + /* Now verify our data doesn't match */ + assert(fork_data->af_parent != fork_data->af_child); + + /* + * For the buffer here, we're mostly concerned that they aren't somehow + * getting the same stream. + */ + for (i = 0; i < sizeof (fork_data->af_pbuf); i++) { + if (fork_data->af_pbuf[i] != fork_data->af_cbuf[i]) + break; + } + assert(i != sizeof (fork_data->af_pbuf)); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/arc4random_forkall.c b/usr/src/test/libc-tests/tests/random/arc4random_forkall.c new file mode 100644 index 0000000000..badd3fe9e8 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/arc4random_forkall.c @@ -0,0 +1,82 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Tests to make sure that a parent and child do not get the same arc4random + * state across a forkall. This source file is used to make two tests. One which + * initializes the data in advance, one of which does not. + */ + +#include <stdlib.h> +#include <sys/mman.h> +#include <assert.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/wait.h> + +typedef struct arc4_fork { + uint32_t af_parent; + uint32_t af_child; + uint8_t af_pbuf[4096]; + uint8_t af_cbuf[4096]; +} arc4_fork_t; + +arc4_fork_t *fork_data; + +int +main(void) +{ + int e, i; + pid_t p, child; + +#ifdef ARC4_PREINIT + (void) arc4random(); +#endif + + fork_data = (arc4_fork_t *)mmap(NULL, sizeof (arc4_fork_t), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + assert(fork_data != MAP_FAILED); + + p = forkall(); + assert(p != -1); + if (p == 0) { + fork_data->af_child = arc4random(); + arc4random_buf(fork_data->af_cbuf, sizeof (fork_data->af_cbuf)); + exit(0); + } + + fork_data->af_parent = arc4random(); + arc4random_buf(fork_data->af_pbuf, sizeof (fork_data->af_pbuf)); + do { + child = wait(&e); + } while (child == -1 && errno == EINTR); + assert(child == p); + + /* Now verify our data doesn't match */ + assert(fork_data->af_parent != fork_data->af_child); + + /* + * For the buffer here, we're mostly concerned that they aren't somehow + * getting the same stream. + */ + for (i = 0; i < sizeof (fork_data->af_pbuf); i++) { + if (fork_data->af_pbuf[i] != fork_data->af_cbuf[i]) + break; + } + assert(i != sizeof (fork_data->af_pbuf)); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/arc4random_forksig.c b/usr/src/test/libc-tests/tests/random/arc4random_forksig.c new file mode 100644 index 0000000000..38d96324e6 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/arc4random_forksig.c @@ -0,0 +1,102 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Tests to make sure that a parent and child do not get the same arc4random + * state across a fork from a signal handler. This source file is used to make + * two tests. One which initializes the data in advance, one of which does not. + */ + +#include <stdlib.h> +#include <sys/mman.h> +#include <assert.h> +#include <errno.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <strings.h> + +typedef struct arc4_fork { + uint32_t af_parent; + uint32_t af_child; + uint8_t af_pbuf[4096]; + uint8_t af_cbuf[4096]; +} arc4_fork_t; + +arc4_fork_t *fork_data; +static pid_t pid; + +/*ARGSUSED*/ +static void +siguser_fork(int sig, siginfo_t *sip, void *ucp) +{ + pid = fork(); +} + +int +main(void) +{ + int e, i, ret; + pid_t child; + struct sigaction sact; + + bzero(&sact, sizeof (struct sigaction)); + sact.sa_flags = SA_SIGINFO; + sact.sa_sigaction = siguser_fork; + + (void) sigemptyset(&sact.sa_mask); + ret = sigaction(SIGUSR1, &sact, NULL); + assert(ret == 0); + +#ifdef ARC4_PREINIT + (void) arc4random(); +#endif + + fork_data = (arc4_fork_t *)mmap(NULL, sizeof (arc4_fork_t), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + assert(fork_data != MAP_FAILED); + + ret = raise(SIGUSR1); + assert(ret == 0); + assert(pid != -1); + if (pid == 0) { + fork_data->af_child = arc4random(); + arc4random_buf(fork_data->af_cbuf, sizeof (fork_data->af_cbuf)); + exit(0); + } + + fork_data->af_parent = arc4random(); + arc4random_buf(fork_data->af_pbuf, sizeof (fork_data->af_pbuf)); + do { + child = wait(&e); + } while (child == -1 && errno == EINTR); + assert(child == pid); + + /* Now verify our data doesn't match */ + assert(fork_data->af_parent != fork_data->af_child); + + /* + * For the buffer here, we're mostly concerned that they aren't somehow + * getting the same stream. + */ + for (i = 0; i < sizeof (fork_data->af_pbuf); i++) { + if (fork_data->af_pbuf[i] != fork_data->af_cbuf[i]) + break; + } + assert(i != sizeof (fork_data->af_pbuf)); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/arc4random_rekey.c b/usr/src/test/libc-tests/tests/random/arc4random_rekey.c new file mode 100644 index 0000000000..923c62a39f --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/arc4random_rekey.c @@ -0,0 +1,39 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * This test is designed to fill a buffer with arc4random_buf and ensure that we + * rekey ourselves multiple times during this test. We have a 4 Mb buffer and + * currently we rekey ourselves every ~1.53 Mb. A wrapper script should call + * this with an appropriate bit of D to verify the rekey. + */ + +#include <stdlib.h> +#include <assert.h> +#include <errno.h> + +#define NENTS (4 * 1024 * 1024) + +int +main(void) +{ + uint8_t *buf; + + buf = malloc(NENTS); + assert(buf != NULL); + arc4random_buf(buf, NENTS); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/chacha_tv.c b/usr/src/test/libc-tests/tests/random/chacha_tv.c new file mode 100644 index 0000000000..636ee114c8 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/chacha_tv.c @@ -0,0 +1,309 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Test chacha20 key stream with known TVs. + * + * Based on data from: + * https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01 + */ + +#include <strings.h> +#include <chacha.h> +#include <assert.h> + +/* Test Vector 1 */ + +static uint8_t cha_key1[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t cha_iv1[8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t cha_fbl1[] = { + 0x89, 0x67, 0x09, 0x52, 0x60, 0x83, 0x64, 0xfd, + 0x00, 0xb2, 0xf9, 0x09, 0x36, 0xf0, 0x31, 0xc8, + 0xe7, 0x56, 0xe1, 0x5d, 0xba, 0x04, 0xb8, 0x49, + 0x3d, 0x00, 0x42, 0x92, 0x59, 0xb2, 0x0f, 0x46, + 0xcc, 0x04, 0xf1, 0x11, 0x24, 0x6b, 0x6c, 0x2c, + 0xe0, 0x66, 0xbe, 0x3b, 0xfb, 0x32, 0xd9, 0xaa, + 0x0f, 0xdd, 0xfb, 0xc1, 0x21, 0x23, 0xd4, 0xb9, + 0xe4, 0x4f, 0x34, 0xdc, 0xa0, 0x5a, 0x10, 0x3f +}; +static uint8_t cha_sbl1[] = { + 0x6c, 0xd1, 0x35, 0xc2, 0x87, 0x8c, 0x83, 0x2b, + 0x58, 0x96, 0xb1, 0x34, 0xf6, 0x14, 0x2a, 0x9d, + 0x4d, 0x8d, 0x0d, 0x8f, 0x10, 0x26, 0xd2, 0x0a, + 0x0a, 0x81, 0x51, 0x2c, 0xbc, 0xe6, 0xe9, 0x75, + 0x8a, 0x71, 0x43, 0xd0, 0x21, 0x97, 0x80, 0x22, + 0xa3, 0x84, 0x14, 0x1a, 0x80, 0xce, 0xa3, 0x06, + 0x2f, 0x41, 0xf6, 0x7a, 0x75, 0x2e, 0x66, 0xad, + 0x34, 0x11, 0x98, 0x4c, 0x78, 0x7e, 0x30, 0xad +}; + +/* Test Vector 2 */ +static uint8_t cha_key2[16] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t cha_iv2[8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static uint8_t cha_fbl2[] = { + 0xae, 0x56, 0x06, 0x0d, 0x04, 0xf5, 0xb5, 0x97, + 0x89, 0x7f, 0xf2, 0xaf, 0x13, 0x88, 0xdb, 0xce, + 0xff, 0x5a, 0x2a, 0x49, 0x20, 0x33, 0x5d, 0xc1, + 0x7a, 0x3c, 0xb1, 0xb1, 0xb1, 0x0f, 0xbe, 0x70, + 0xec, 0xe8, 0xf4, 0x86, 0x4d, 0x8c, 0x7c, 0xdf, + 0x00, 0x76, 0x45, 0x3a, 0x82, 0x91, 0xc7, 0xdb, + 0xeb, 0x3a, 0xa9, 0xc9, 0xd1, 0x0e, 0x8c, 0xa3, + 0x6b, 0xe4, 0x44, 0x93, 0x76, 0xed, 0x7c, 0x42 +}; + +static uint8_t cha_sbl2[] = { + 0xfc, 0x3d, 0x47, 0x1c, 0x34, 0xa3, 0x6f, 0xbb, + 0xf6, 0x16, 0xbc, 0x0a, 0x0e, 0x7c, 0x52, 0x30, + 0x30, 0xd9, 0x44, 0xf4, 0x3e, 0xc3, 0xe7, 0x8d, + 0xd6, 0xa1, 0x24, 0x66, 0x54, 0x7c, 0xb4, 0xf7, + 0xb3, 0xce, 0xbd, 0x0a, 0x50, 0x05, 0xe7, 0x62, + 0xe5, 0x62, 0xd1, 0x37, 0x5b, 0x7a, 0xc4, 0x45, + 0x93, 0xa9, 0x91, 0xb8, 0x5d, 0x1a, 0x60, 0xfb, + 0xa2, 0x03, 0x5d, 0xfa, 0xa2, 0xa6, 0x42, 0xd5 +}; + +/* Test Vector 3 */ +static uint8_t cha_key3[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static uint8_t cha_iv3[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static uint8_t cha_fbl3[] = { + 0x16, 0x63, 0x87, 0x9e, 0xb3, 0xf2, 0xc9, 0x94, + 0x9e, 0x23, 0x88, 0xca, 0xa3, 0x43, 0xd3, 0x61, + 0xbb, 0x13, 0x27, 0x71, 0x24, 0x5a, 0xe6, 0xd0, + 0x27, 0xca, 0x9c, 0xb0, 0x10, 0xdc, 0x1f, 0xa7, + 0x17, 0x8d, 0xc4, 0x1f, 0x82, 0x78, 0xbc, 0x1f, + 0x64, 0xb3, 0xf1, 0x27, 0x69, 0xa2, 0x40, 0x97, + 0xf4, 0x0d, 0x63, 0xa8, 0x63, 0x66, 0xbd, 0xb3, + 0x6a, 0xc0, 0x8a, 0xbe, 0x60, 0xc0, 0x7f, 0xe8 +}; + +static uint8_t cha_sbl3[] = { + 0xb0, 0x57, 0x37, 0x5c, 0x89, 0x14, 0x44, 0x08, + 0xcc, 0x74, 0x46, 0x24, 0xf6, 0x9f, 0x7f, 0x4c, + 0xcb, 0xd9, 0x33, 0x66, 0xc9, 0x2f, 0xc4, 0xdf, + 0xca, 0xda, 0x65, 0xf1, 0xb9, 0x59, 0xd8, 0xc6, + 0x4d, 0xfc, 0x50, 0xde, 0x71, 0x1f, 0xb4, 0x64, + 0x16, 0xc2, 0x55, 0x3c, 0xc6, 0x0f, 0x21, 0xbb, + 0xfd, 0x00, 0x64, 0x91, 0xcb, 0x17, 0x88, 0x8b, + 0x4f, 0xb3, 0x52, 0x1c, 0x4f, 0xdd, 0x87, 0x45 +}; + +/* Test Vector 4 */ +static uint8_t cha_key4[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static uint8_t cha_iv4[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static uint8_t cha_fbl4[] = { + 0x99, 0x29, 0x47, 0xc3, 0x96, 0x61, 0x26, 0xa0, + 0xe6, 0x60, 0xa3, 0xe9, 0x5d, 0xb0, 0x48, 0xde, + 0x09, 0x1f, 0xb9, 0xe0, 0x18, 0x5b, 0x1e, 0x41, + 0xe4, 0x10, 0x15, 0xbb, 0x7e, 0xe5, 0x01, 0x50, + 0x39, 0x9e, 0x47, 0x60, 0xb2, 0x62, 0xf9, 0xd5, + 0x3f, 0x26, 0xd8, 0xdd, 0x19, 0xe5, 0x6f, 0x5c, + 0x50, 0x6a, 0xe0, 0xc3, 0x61, 0x9f, 0xa6, 0x7f, + 0xb0, 0xc4, 0x08, 0x10, 0x6d, 0x02, 0x03, 0xee +}; + +static uint8_t cha_sbl4[] = { + 0x40, 0xea, 0x3c, 0xfa, 0x61, 0xfa, 0x32, 0xa2, + 0xfd, 0xa8, 0xd1, 0x23, 0x8a, 0x21, 0x35, 0xd9, + 0xd4, 0x17, 0x87, 0x75, 0x24, 0x0f, 0x99, 0x00, + 0x70, 0x64, 0xa6, 0xa7, 0xf0, 0xc7, 0x31, 0xb6, + 0x7c, 0x22, 0x7c, 0x52, 0xef, 0x79, 0x6b, 0x6b, + 0xed, 0x9f, 0x90, 0x59, 0xba, 0x06, 0x14, 0xbc, + 0xf6, 0xdd, 0x6e, 0x38, 0x91, 0x7f, 0x3b, 0x15, + 0x0e, 0x57, 0x63, 0x75, 0xbe, 0x50, 0xed, 0x67 +}; + +/* Test Vector 5 */ +static uint8_t cha_key5[] = { + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 +}; +static uint8_t cha_iv5[] = { + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 +}; + +static uint8_t cha_fbl5[] = { + 0x35, 0x7d, 0x7d, 0x94, 0xf9, 0x66, 0x77, 0x8f, + 0x58, 0x15, 0xa2, 0x05, 0x1d, 0xcb, 0x04, 0x13, + 0x3b, 0x26, 0xb0, 0xea, 0xd9, 0xf5, 0x7d, 0xd0, + 0x99, 0x27, 0x83, 0x7b, 0xc3, 0x06, 0x7e, 0x4b, + 0x6b, 0xf2, 0x99, 0xad, 0x81, 0xf7, 0xf5, 0x0c, + 0x8d, 0xa8, 0x3c, 0x78, 0x10, 0xbf, 0xc1, 0x7b, + 0xb6, 0xf4, 0x81, 0x3a, 0xb6, 0xc3, 0x26, 0x95, + 0x70, 0x45, 0xfd, 0x3f, 0xd5, 0xe1, 0x99, 0x15 +}; + +static uint8_t cha_sbl5[] = { + 0xec, 0x74, 0x4a, 0x6b, 0x9b, 0xf8, 0xcb, 0xdc, + 0xb3, 0x6d, 0x8b, 0x6a, 0x54, 0x99, 0xc6, 0x8a, + 0x08, 0xef, 0x7b, 0xe6, 0xcc, 0x1e, 0x93, 0xf2, + 0xf5, 0xbc, 0xd2, 0xca, 0xd4, 0xe4, 0x7c, 0x18, + 0xa3, 0xe5, 0xd9, 0x4b, 0x56, 0x66, 0x38, 0x2c, + 0x6d, 0x13, 0x0d, 0x82, 0x2d, 0xd5, 0x6a, 0xac, + 0xb0, 0xf8, 0x19, 0x52, 0x78, 0xe7, 0xb2, 0x92, + 0x49, 0x5f, 0x09, 0x86, 0x8d, 0xdf, 0x12, 0xcc +}; + +/* Test Vector 6 */ + +static uint8_t cha_key6[] = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa +}; +static uint8_t cha_iv6[] = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa +}; + +static uint8_t cha_fbl6[] = { + 0xfc, 0x79, 0xac, 0xbd, 0x58, 0x52, 0x61, 0x03, + 0x86, 0x27, 0x76, 0xaa, 0xb2, 0x0f, 0x3b, 0x7d, + 0x8d, 0x31, 0x49, 0xb2, 0xfa, 0xb6, 0x57, 0x66, + 0x29, 0x93, 0x16, 0xb6, 0xe5, 0xb1, 0x66, 0x84, + 0xde, 0x5d, 0xe5, 0x48, 0xc1, 0xb7, 0xd0, 0x83, + 0xef, 0xd9, 0xe3, 0x05, 0x23, 0x19, 0xe0, 0xc6, + 0x25, 0x41, 0x41, 0xda, 0x04, 0xa6, 0x58, 0x6d, + 0xf8, 0x00, 0xf6, 0x4d, 0x46, 0xb0, 0x1c, 0x87 +}; + +static uint8_t cha_sbl6[] = { + 0x1f, 0x05, 0xbc, 0x67, 0xe0, 0x76, 0x28, 0xeb, + 0xe6, 0xf6, 0x86, 0x5a, 0x21, 0x77, 0xe0, 0xb6, + 0x6a, 0x55, 0x8a, 0xa7, 0xcc, 0x1e, 0x8f, 0xf1, + 0xa9, 0x8d, 0x27, 0xf7, 0x07, 0x1f, 0x83, 0x35, + 0xef, 0xce, 0x45, 0x37, 0xbb, 0x0e, 0xf7, 0xb5, + 0x73, 0xb3, 0x2f, 0x32, 0x76, 0x5f, 0x29, 0x00, + 0x7d, 0xa5, 0x3b, 0xba, 0x62, 0xe7, 0xa4, 0x4d, + 0x00, 0x6f, 0x41, 0xeb, 0x28, 0xfe, 0x15, 0xd6 +}; + +/* Test Vector 7 */ +static uint8_t cha_key7[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff +}; +static uint8_t cha_iv7[] = { + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78 +}; + +static uint8_t cha_fbl7[] = { + 0xd1, 0xab, 0xf6, 0x30, 0x46, 0x7e, 0xb4, 0xf6, + 0x7f, 0x1c, 0xfb, 0x47, 0xcd, 0x62, 0x6a, 0xae, + 0x8a, 0xfe, 0xdb, 0xbe, 0x4f, 0xf8, 0xfc, 0x5f, + 0xe9, 0xcf, 0xae, 0x30, 0x7e, 0x74, 0xed, 0x45, + 0x1f, 0x14, 0x04, 0x42, 0x5a, 0xd2, 0xb5, 0x45, + 0x69, 0xd5, 0xf1, 0x81, 0x48, 0x93, 0x99, 0x71, + 0xab, 0xb8, 0xfa, 0xfc, 0x88, 0xce, 0x4a, 0xc7, + 0xfe, 0x1c, 0x3d, 0x1f, 0x7a, 0x1e, 0xb7, 0xca +}; + +static uint8_t cha_sbl7[] = { + 0xe7, 0x6c, 0xa8, 0x7b, 0x61, 0xa9, 0x71, 0x35, + 0x41, 0x49, 0x77, 0x60, 0xdd, 0x9a, 0xe0, 0x59, + 0x35, 0x0c, 0xad, 0x0d, 0xce, 0xdf, 0xaa, 0x80, + 0xa8, 0x83, 0x11, 0x9a, 0x1a, 0x6f, 0x98, 0x7f, + 0xd1, 0xce, 0x91, 0xfd, 0x8e, 0xe0, 0x82, 0x80, + 0x34, 0xb4, 0x11, 0x20, 0x0a, 0x97, 0x45, 0xa2, + 0x85, 0x55, 0x44, 0x75, 0xd1, 0x2a, 0xfc, 0x04, + 0x88, 0x7f, 0xef, 0x35, 0x16, 0xd1, 0x2a, 0x2c +}; + +/* Test Vector 8 */ +static uint8_t cha_key8[] = { + 0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78, + 0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35 +}; +static uint8_t cha_iv8[] = { + 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21 +}; + +static uint8_t cha_fbl8[] = { + 0x82, 0x6a, 0xbd, 0xd8, 0x44, 0x60, 0xe2, 0xe9, + 0x34, 0x9f, 0x0e, 0xf4, 0xaf, 0x5b, 0x17, 0x9b, + 0x42, 0x6e, 0x4b, 0x2d, 0x10, 0x9a, 0x9c, 0x5b, + 0xb4, 0x40, 0x00, 0xae, 0x51, 0xbe, 0xa9, 0x0a, + 0x49, 0x6b, 0xee, 0xef, 0x62, 0xa7, 0x68, 0x50, + 0xff, 0x3f, 0x04, 0x02, 0xc4, 0xdd, 0xc9, 0x9f, + 0x6d, 0xb0, 0x7f, 0x15, 0x1c, 0x1c, 0x0d, 0xfa, + 0xc2, 0xe5, 0x65, 0x65, 0xd6, 0x28, 0x96, 0x25 +}; + +static uint8_t cha_sbl8[] = { + 0x5b, 0x23, 0x13, 0x2e, 0x7b, 0x46, 0x9c, 0x7b, + 0xfb, 0x88, 0xfa, 0x95, 0xd4, 0x4c, 0xa5, 0xae, + 0x3e, 0x45, 0xe8, 0x48, 0xa4, 0x10, 0x8e, 0x98, + 0xba, 0xd7, 0xa9, 0xeb, 0x15, 0x51, 0x27, 0x84, + 0xa6, 0xa9, 0xe6, 0xe5, 0x91, 0xdc, 0xe6, 0x74, + 0x12, 0x0a, 0xca, 0xf9, 0x04, 0x0f, 0xf5, 0x0f, + 0xf3, 0xac, 0x30, 0xcc, 0xfb, 0x5e, 0x14, 0x20, + 0x4f, 0x5e, 0x42, 0x68, 0xb9, 0x0a, 0x88, 0x04 +}; + +static void +chacha_test(uint8_t *key, uint8_t keylen, uint8_t *iv, uint8_t *bl0, + uint8_t *bl1) +{ + uint8_t res0[64], res1[64]; + chacha_ctx_t ctx; + int ret; + + bzero(&ctx, sizeof (ctx)); + bzero(res0, sizeof (res0)); + bzero(res1, sizeof (res1)); + chacha_keysetup(&ctx, key, keylen * 8, 0); + chacha_ivsetup(&ctx, iv); + chacha_encrypt_bytes(&ctx, res0, res0, sizeof (res0)); + chacha_encrypt_bytes(&ctx, res1, res1, sizeof (res1)); + ret = bcmp(res0, bl0, sizeof (res0)); + assert(ret == 0); + ret = bcmp(res1, bl1, sizeof (res0)); + assert(ret == 0); +} + +int +main(void) +{ + chacha_test(cha_key1, sizeof (cha_key1), cha_iv1, cha_fbl1, cha_sbl1); + chacha_test(cha_key2, sizeof (cha_key2), cha_iv2, cha_fbl2, cha_sbl2); + chacha_test(cha_key3, sizeof (cha_key3), cha_iv3, cha_fbl3, cha_sbl3); + chacha_test(cha_key4, sizeof (cha_key4), cha_iv4, cha_fbl4, cha_sbl4); + chacha_test(cha_key5, sizeof (cha_key5), cha_iv5, cha_fbl5, cha_sbl5); + chacha_test(cha_key6, sizeof (cha_key6), cha_iv6, cha_fbl6, cha_sbl6); + chacha_test(cha_key7, sizeof (cha_key7), cha_iv7, cha_fbl7, cha_sbl7); + chacha_test(cha_key8, sizeof (cha_key8), cha_iv8, cha_fbl8, cha_sbl8); + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/getentropy.c b/usr/src/test/libc-tests/tests/random/getentropy.c new file mode 100644 index 0000000000..7d5b35993c --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/getentropy.c @@ -0,0 +1,66 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Test getentropy(3C) + */ + +#include <unistd.h> +#include <sys/mman.h> +#include <assert.h> +#include <errno.h> + +int +main(void) +{ + int ret; + void *addr; + uint8_t errbuf[512]; + uint8_t buf[128]; + + ret = getentropy(buf, sizeof (buf)); + assert(ret == 0); + + /* Max buffer is 256 bytes, verify if we go larger, we error */ + ret = getentropy(errbuf, sizeof (errbuf)); + assert(ret == -1); + assert(errno == EIO); + + ret = getentropy(errbuf, 257); + assert(ret == -1); + assert(errno == EIO); + + ret = getentropy(errbuf, 256); + assert(ret == 0); + + ret = getentropy(errbuf, 0); + assert(ret == 0); + + /* Bad buffers */ + ret = getentropy(NULL, sizeof (buf)); + assert(ret == -1); + assert(errno == EFAULT); + + /* Jump through a hoop to know we'll always have a bad address */ + addr = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + assert(addr != MAP_FAILED); + ret = munmap(addr, 4096); + assert(ret == 0); + ret = getentropy(addr, sizeof (buf)); + assert(ret == -1); + assert(errno == EFAULT); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/getrandom.c b/usr/src/test/libc-tests/tests/random/getrandom.c new file mode 100644 index 0000000000..b7ba90362c --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/getrandom.c @@ -0,0 +1,86 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Test getrandom(2) + */ + +#include <sys/random.h> +#include <sys/mman.h> +#include <assert.h> +#include <errno.h> + +int +main(void) +{ + int ret; + void *addr; + uint8_t buf[32]; + uint8_t bigbuf[4096]; + + /* Go through flags values, start with invalid */ + ret = getrandom(buf, sizeof (buf), 42); + assert(ret == -1); + assert(errno == EINVAL); + + ret = getrandom(buf, sizeof (buf), 0); + assert(ret >= 0); + + ret = getrandom(buf, sizeof (buf), GRND_NONBLOCK); + assert(ret >= 0); + + ret = getrandom(buf, sizeof (buf), GRND_RANDOM); + assert(ret >= 0); + + ret = getrandom(buf, sizeof (buf), GRND_RANDOM | GRND_NONBLOCK); + assert(ret >= 0); + + ret = getrandom(buf, sizeof (buf), (GRND_RANDOM | GRND_NONBLOCK) << 1); + assert(ret == -1); + assert(errno == EINVAL); + + /* Bad buffer addresses, eg. EFAULT */ + ret = getrandom(NULL, sizeof (buf), 0); + assert(ret == -1); + assert(errno == EFAULT); + + ret = getrandom(NULL, sizeof (buf), GRND_RANDOM); + assert(ret == -1); + assert(errno == EFAULT); + + /* Jump through a hoop to know we'll always have a bad address */ + addr = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); + assert(addr != MAP_FAILED); + ret = munmap(addr, 4096); + assert(ret == 0); + ret = getrandom(addr, sizeof (buf), 0); + assert(ret == -1); + assert(errno == EFAULT); + ret = getrandom(addr, sizeof (buf), GRND_RANDOM); + assert(ret == -1); + assert(errno == EFAULT); + + /* Verify that we get rounded down on a getrandom of /dev/random */ + ret = getrandom(bigbuf, sizeof (buf), GRND_RANDOM); + assert(ret >= 0 && ret < sizeof (bigbuf)); + + /* Do a few simple sets where we know we should get data */ + ret = getrandom(buf, sizeof (buf), 0); + assert(ret == sizeof (buf)); + ret = getrandom(buf, sizeof (buf), GRND_RANDOM); + assert(ret == sizeof (buf)); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/inz_child.c b/usr/src/test/libc-tests/tests/random/inz_child.c new file mode 100644 index 0000000000..c62214f753 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/inz_child.c @@ -0,0 +1,73 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Verify that using MC_INHERIT_ZERO works just fine when applied to an entire + * region across multiple children. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <wait.h> + +static int nchild = 5; + +int +main(void) +{ + void *buf; + pid_t child; + int ret, i; + siginfo_t info; + uint8_t *ubuf; + size_t mapsz = sysconf(_SC_PAGESIZE) * 2; + + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == 0); + +again: + memset(buf, 'a' + nchild, mapsz); + child = fork(); + if (child == 0) { + nchild--; + for (i = 0, ubuf = buf; i < mapsz; i++) + assert(ubuf[i] == 0); + if (nchild != 0) + goto again; + exit(0); + } + assert(child != -1); + + do { + ret = waitid(P_PID, child, &info, WEXITED); + } while (ret == -1 && errno == EINTR); + assert(ret == 0); + assert(info.si_pid == child); + assert(info.si_status == 0); + + for (i = 0, ubuf = buf; i < mapsz; i++) + assert(ubuf[i] == 'a' + nchild); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/inz_inval.c b/usr/src/test/libc-tests/tests/random/inz_inval.c new file mode 100644 index 0000000000..1032814b25 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/inz_inval.c @@ -0,0 +1,113 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Verify that using MC_INHERIT_ZERO doesn't work on mappings that aren't + * anonymous private mappings. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <wait.h> +#include <sys/stat.h> +#include <fcntl.h> + +int +main(void) +{ + void *buf; + int ret, fd; + char *template = "/tmp/inz_inval.XXXXXX"; + char *tmpfile; + size_t mapsz = sysconf(_SC_PAGESIZE) * 2; + caddr_t bad = (caddr_t)(uintptr_t)23; + + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + + /* Bad arguments to memcntl */ + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, bad, 0, 0); + assert(ret == -1); + assert(errno == EINVAL); + + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, PROT_READ, 0); + assert(ret == -1); + assert(errno == EINVAL); + + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, bad, PROT_READ | PRIVATE, 0); + assert(ret == -1); + assert(errno == EINVAL); + + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 1); + assert(ret == -1); + assert(errno == EINVAL); + + ret = munmap(buf, mapsz); + assert(ret == 0); + + /* Mapping non-existant region */ + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == -1); + assert(errno == ENOMEM); + + /* Map anon MAP_SHARED */ + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == -1); + assert(errno == EINVAL); + ret = munmap(buf, mapsz); + assert(ret == 0); + + /* Grab a temp file and get it to be the right size */ + tmpfile = strdup(template); + assert(tmpfile != NULL); + fd = mkstemp(tmpfile); + assert(fd >= 0); + ret = ftruncate(fd, mapsz); + assert(ret == 0); + + /* MAP_PRIVATE file */ + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + assert(buf != MAP_FAILED); + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == -1); + assert(errno == EINVAL); + ret = munmap(buf, mapsz); + assert(ret == 0); + + /* MAP_SHARED file */ + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + assert(buf != MAP_FAILED); + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == -1); + assert(errno == EINVAL); + ret = munmap(buf, mapsz); + assert(ret == 0); + + ret = close(fd); + assert(ret == 0); + (void) unlink(tmpfile); + free(tmpfile); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/inz_mlock.c b/usr/src/test/libc-tests/tests/random/inz_mlock.c new file mode 100644 index 0000000000..863c38a0fc --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/inz_mlock.c @@ -0,0 +1,70 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Verify that using MC_INHERIT_ZERO works just fine when applied to an entire + * region that is mlocked. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <wait.h> + +int +main(void) +{ + void *buf; + pid_t child; + int ret, i; + siginfo_t info; + uint8_t *ubuf; + size_t mapsz = sysconf(_SC_PAGESIZE) * 2; + + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + memset(buf, 'a', mapsz); + + ret = mlock(buf, mapsz); + assert(ret == 0); + + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == 0); + + child = fork(); + if (child == 0) { + for (i = 0, ubuf = buf; i < mapsz; i++) + assert(ubuf[i] == 0); + exit(0); + } + assert(child != -1); + + do { + ret = waitid(P_PID, child, &info, WEXITED); + } while (ret == -1 && errno == EINTR); + assert(ret == 0); + assert(info.si_pid == child); + assert(info.si_status == 0); + + for (i = 0, ubuf = buf; i < mapsz; i++) + assert(ubuf[i] == 'a'); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/inz_region.c b/usr/src/test/libc-tests/tests/random/inz_region.c new file mode 100644 index 0000000000..a6af41f7ee --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/inz_region.c @@ -0,0 +1,67 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Verify that using MC_INHERIT_ZERO works just fine when applied to an entire + * region. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <wait.h> + +int +main(void) +{ + void *buf; + pid_t child; + int ret, i; + siginfo_t info; + uint8_t *ubuf; + size_t mapsz = sysconf(_SC_PAGESIZE) * 2; + + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + memset(buf, 'a', mapsz); + + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == 0); + + child = fork(); + if (child == 0) { + for (i = 0, ubuf = buf; i < mapsz; i++) + assert(ubuf[i] == 0); + exit(0); + } + assert(child != -1); + + do { + ret = waitid(P_PID, child, &info, WEXITED); + } while (ret == -1 && errno == EINTR); + assert(ret == 0); + assert(info.si_pid == child); + assert(info.si_status == 0); + + for (i = 0, ubuf = buf; i < mapsz; i++) + assert(ubuf[i] == 'a'); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/inz_split.c b/usr/src/test/libc-tests/tests/random/inz_split.c new file mode 100644 index 0000000000..829cb85bdb --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/inz_split.c @@ -0,0 +1,78 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Verify that using MC_INHERIT_ZERO works just fine when applied to an entire + * region that then gets split in half, hence creating new segments. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <wait.h> + +int +main(void) +{ + void *buf; + pid_t child; + int ret, i; + siginfo_t info; + uint8_t *ubuf; + size_t mapsz = sysconf(_SC_PAGESIZE) * 8; + size_t spltsz = sysconf(_SC_PAGESIZE) * 4; + size_t spltoff = sysconf(_SC_PAGESIZE) * 2; + + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + memset(buf, 'a', mapsz); + + ret = memcntl(buf, mapsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == 0); + + ret = munmap(buf + spltoff, spltsz); + assert(ret == 0); + + child = fork(); + if (child == 0) { + ubuf = buf; + for (i = 0; i < spltoff; i++) + assert(ubuf[i] == 0); + for (i = spltoff + spltsz; i < mapsz; i++) + assert(ubuf[i] == 0); + exit(0); + } + assert(child != -1); + + do { + ret = waitid(P_PID, child, &info, WEXITED); + } while (ret == -1 && errno == EINTR); + assert(ret == 0); + assert(info.si_pid == child); + assert(info.si_status == 0); + + ubuf = buf; + for (i = 0; i < spltoff; i++) + assert(ubuf[i] == 'a'); + for (i = spltoff + spltsz; i < mapsz; i++) + assert(ubuf[i] == 'a'); + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/inz_split_vpp.c b/usr/src/test/libc-tests/tests/random/inz_split_vpp.c new file mode 100644 index 0000000000..6dff8d795c --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/inz_split_vpp.c @@ -0,0 +1,92 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Verify that using MC_INHERIT_ZERO works just fine when applied to a subset of + * a region, meaning that we should have created a struct vpage for that region. + * Then unmap a hole in the middle, so that way we force subsets of children + * that have struct vpage entries. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <wait.h> + +int +main(void) +{ + void *buf; + pid_t child; + int ret, i; + siginfo_t info; + uint8_t *ubuf; + size_t pgsz = sysconf(_SC_PAGESIZE); + size_t mapsz = 10 * pgsz; + size_t clrsz = 5 * pgsz; + size_t clroff = 2 * pgsz; + size_t spltsz = 1 * pgsz; + size_t spltoff = 3 * pgsz; + + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + memset(buf, 'a', mapsz); + + ret = memcntl(buf + clroff, clrsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == 0); + + ret = munmap(buf + spltoff, spltsz); + assert(ret == 0); + + child = fork(); + if (child == 0) { + ubuf = buf; + for (i = 0; i < clroff; i++) + assert(ubuf[i] == 'a'); + for (i = clroff; i < spltoff; i++) + assert(ubuf[i] == 0); + for (i = spltoff + spltsz; i < clroff + clrsz; i++) + assert(ubuf[i] == 0); + for (i = clrsz + clroff; i < mapsz; i++) + assert(ubuf[i] == 'a'); + exit(0); + } + assert(child != -1); + + do { + ret = waitid(P_PID, child, &info, WEXITED); + } while (ret == -1 && errno == EINTR); + assert(ret == 0); + assert(info.si_pid == child); + assert(info.si_status == 0); + + ubuf = buf; + for (i = 0; i < clroff; i++) + assert(ubuf[i] == 'a'); + for (i = clroff; i < spltoff; i++) + assert(ubuf[i] == 'a'); + for (i = spltoff + spltsz; i < clroff + clrsz; i++) + assert(ubuf[i] == 'a'); + for (i = clrsz + clroff; i < mapsz; i++) + assert(ubuf[i] == 'a'); + + + return (0); +} diff --git a/usr/src/test/libc-tests/tests/random/inz_vpp.c b/usr/src/test/libc-tests/tests/random/inz_vpp.c new file mode 100644 index 0000000000..f33575c591 --- /dev/null +++ b/usr/src/test/libc-tests/tests/random/inz_vpp.c @@ -0,0 +1,75 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * Verify that using MC_INHERIT_ZERO works just fine when applied to a subset of + * a region, meaning that we should have created a struct vpage for that region. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <assert.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <wait.h> + +int +main(void) +{ + void *buf; + pid_t child; + int ret, i; + siginfo_t info; + uint8_t *ubuf; + size_t pgsz = sysconf(_SC_PAGESIZE); + size_t mapsz = 10 * pgsz; + size_t clrsz = 5 * pgsz; + size_t clroff = 2 * pgsz; + + buf = mmap(NULL, mapsz, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + assert(buf != MAP_FAILED); + memset(buf, 'a', mapsz); + + ret = memcntl(buf + clroff, clrsz, MC_INHERIT_ZERO, 0, 0, 0); + assert(ret == 0); + + child = fork(); + if (child == 0) { + ubuf = buf; + for (i = 0; i < clroff; i++) + assert(ubuf[i] == 'a'); + for (i = clroff; i < clrsz + clroff; i++) + assert(ubuf[i] == 0); + for (i = clrsz + clroff; i < mapsz; i++) + assert(ubuf[i] == 'a'); + exit(0); + } + assert(child != -1); + + do { + ret = waitid(P_PID, child, &info, WEXITED); + } while (ret == -1 && errno == EINTR); + assert(ret == 0); + assert(info.si_pid == child); + assert(info.si_status == 0); + + for (i = 0, ubuf = buf; i < mapsz; i++) + assert(ubuf[i] == 'a'); + + return (0); +} diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 4de1edf971..f022dc69e0 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -277,6 +277,7 @@ GENUNIX_OBJS += \ profil.o \ project.o \ qsort.o \ + getrandom.o \ rctl.o \ rctlsys.o \ readlink.o \ diff --git a/usr/src/uts/common/crypto/api/kcf_random.c b/usr/src/uts/common/crypto/api/kcf_random.c index 7766d8ba7a..75072fb686 100644 --- a/usr/src/uts/common/crypto/api/kcf_random.c +++ b/usr/src/uts/common/crypto/api/kcf_random.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ /* @@ -1096,3 +1097,13 @@ random_get_bytes(uint8_t *ptr, size_t len) return (0); return (kcf_rnd_get_bytes(ptr, len, B_TRUE)); } + +int +random_get_blocking_bytes(uint8_t *ptr, size_t len) +{ + ASSERT(!mutex_owned(&rndpool_lock)); + + if (len < 1) + return (0); + return (kcf_rnd_get_bytes(ptr, len, B_FALSE)); +} diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c index edcc85774e..aa44ccf788 100644 --- a/usr/src/uts/common/os/sysent.c +++ b/usr/src/uts/common/os/sysent.c @@ -328,6 +328,7 @@ int getsockopt(int, int, int, void *, socklen_t *, int); int setsockopt(int, int, int, void *, socklen_t *, int); int sockconfig(int, void *, void *, void *, void *); ssize_t sendfilev(int, int, const struct sendfilevec *, int, size_t *); +int getrandom(void *, size_t, int); typedef int64_t (*llfcn_t)(); /* for casting one-word returns */ @@ -582,7 +583,7 @@ struct sysent sysent[NSYSCALL] = /* 123 */ SYSENT_CL("preadv", preadv, 5), /* 124 */ SYSENT_CL("pwritev", pwritev, 5), /* 125 */ SYSENT_LOADABLE(), /* (was fxstat) */ - /* 126 */ SYSENT_LOADABLE(), /* (was xmknod) */ + /* 126 */ SYSENT_CI("getrandom", getrandom, 3), /* 127 */ SYSENT_CI("mmapobj", mmapobjsys, 5), /* 128 */ IF_LP64( SYSENT_CI("setrlimit", setrlimit64, 2), @@ -947,7 +948,7 @@ struct sysent sysent32[NSYSCALL] = /* 123 */ SYSENT_CI("preadv", preadv, 5), /* 124 */ SYSENT_CI("pwritev", pwritev, 5), /* 125 */ SYSENT_LOADABLE32(), /* was fxstat32 */ - /* 126 */ SYSENT_LOADABLE32(), /* was xmknod */ + /* 126 */ SYSENT_CI("getrandom", getrandom, 3), /* 127 */ SYSENT_CI("mmapobj", mmapobjsys, 5), /* 128 */ SYSENT_CI("setrlimit", setrlimit32, 2), /* 129 */ SYSENT_CI("getrlimit", getrlimit32, 2), diff --git a/usr/src/uts/common/sys/mman.h b/usr/src/uts/common/sys/mman.h index 8f4cd1639f..e9ac3a37cc 100644 --- a/usr/src/uts/common/sys/mman.h +++ b/usr/src/uts/common/sys/mman.h @@ -25,7 +25,7 @@ * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2012 Joyent, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -303,7 +303,12 @@ struct memcntl_mha32 { #endif /* !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__) */ #if (_POSIX_C_SOURCE <= 2) && !defined(_XPG4_2) || defined(__EXTENSIONS__) -/* advice to madvise */ +/* + * advice to madvise + * + * Note, if more than 4 bits worth of advice (eg. 16) are specified then + * changes will be necessary to the struct vpage. + */ #define MADV_NORMAL 0 /* no further special treatment */ #define MADV_RANDOM 1 /* expect random page references */ #define MADV_SEQUENTIAL 2 /* expect sequential page references */ @@ -313,6 +318,7 @@ struct memcntl_mha32 { #define MADV_ACCESS_DEFAULT 6 /* default access */ #define MADV_ACCESS_LWP 7 /* next LWP to access heavily */ #define MADV_ACCESS_MANY 8 /* many processes to access heavily */ + #endif /* (_POSIX_C_SOURCE <= 2) && !defined(_XPG4_2) ... */ #if !defined(__XOPEN_OR_POSIX) || defined(_XPG6) || defined(__EXTENSIONS__) @@ -342,6 +348,7 @@ struct memcntl_mha32 { #define MC_LOCKAS 5 /* lock address space in memory */ #define MC_UNLOCKAS 6 /* unlock address space from memory */ #define MC_HAT_ADVISE 7 /* advise hat map size */ +#define MC_INHERIT_ZERO 8 /* zero out regions on fork() */ /* sub-commands for MC_HAT_ADVISE */ #define MHA_MAPSIZE_VA 0x1 /* set preferred page size */ diff --git a/usr/src/uts/common/sys/random.h b/usr/src/uts/common/sys/random.h index a38201456f..b835d2f5ac 100644 --- a/usr/src/uts/common/sys/random.h +++ b/usr/src/uts/common/sys/random.h @@ -24,6 +24,7 @@ */ /* * Copyright 2010 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. */ #ifndef _SYS_RANDOM_H @@ -61,10 +62,19 @@ typedef struct swrand_stats { extern int random_add_entropy(uint8_t *, size_t, uint_t); extern int random_get_bytes(uint8_t *, size_t); +extern int random_get_blocking_bytes(uint8_t *, size_t); extern int random_get_pseudo_bytes(uint8_t *, size_t); #endif /* _KERNEL */ +/* + * Flags for the getrandom system call. Note, we may want to move these + * definitions if we expose getrandom(2) into a public system call. + */ +#define GRND_NONBLOCK 0x0001 /* O_NONBLOCK equiv */ +#define GRND_RANDOM 0x0002 /* Use /dev/random, not /dev/urandom */ +extern int getrandom(void *, size_t, int); + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/syscall.h b/usr/src/uts/common/sys/syscall.h index 5523f08552..7d86565564 100644 --- a/usr/src/uts/common/sys/syscall.h +++ b/usr/src/uts/common/sys/syscall.h @@ -296,6 +296,7 @@ extern "C" { #define SYS_writev 122 #define SYS_preadv 123 #define SYS_pwritev 124 +#define SYS_getrandom 126 #define SYS_mmapobj 127 #define SYS_setrlimit 128 #define SYS_getrlimit 129 diff --git a/usr/src/uts/common/syscall/getrandom.c b/usr/src/uts/common/syscall/getrandom.c new file mode 100644 index 0000000000..46b650b0dc --- /dev/null +++ b/usr/src/uts/common/syscall/getrandom.c @@ -0,0 +1,80 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015, Joyent, Inc. + */ + +/* + * getrandom system call implementation + */ + +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/systm.h> +#include <sys/random.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/sysmacros.h> + +#include <sys/random.h> + +/* + * Impose a maximum upper bound on the number of bytes that we'll read in one + * go, ala a read of /dev/random. For /dev/urandom, we clamp it based on our + * return value, because the system call returns an int, we can't handle more + * than INT_MAX. + */ +#define MAXRANDBYTES 1024 +#define MAXURANDBYTES INT_MAX + +int +getrandom(void *bufp, size_t buflen, int flags) +{ + int out = 0; + uint8_t rbytes[128]; + uint8_t *buf = bufp; + + if (flags & ~(GRND_NONBLOCK | GRND_RANDOM)) + return (set_errno(EINVAL)); + + if ((flags & GRND_RANDOM) && buflen > MAXRANDBYTES) { + buflen = MAXRANDBYTES; + } else if (buflen > MAXURANDBYTES) { + buflen = MAXURANDBYTES; + } + + while (buflen > out) { + int err; + size_t len = MIN(sizeof (rbytes), buflen); + + if (flags & GRND_RANDOM) { + if (flags & GRND_NONBLOCK) + err = random_get_bytes(rbytes, len); + else + err = random_get_blocking_bytes(rbytes, len); + } else { + err = random_get_pseudo_bytes(rbytes, len); + } + + if (err == 0) { + if (ddi_copyout(rbytes, buf + out, len, 0) != 0) + return (set_errno(EFAULT)); + out += len; + } else if (err == EAGAIN && out > 0) { + break; + } else { + return (set_errno(err)); + } + } + + return (out); +} diff --git a/usr/src/uts/common/syscall/memcntl.c b/usr/src/uts/common/syscall/memcntl.c index 63c8b64ad0..4f220bbca5 100644 --- a/usr/src/uts/common/syscall/memcntl.c +++ b/usr/src/uts/common/syscall/memcntl.c @@ -21,15 +21,13 @@ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2012 Joyent, Inc. All rights reserved. + * Copyright (c) 2015 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/bitmap.h> #include <sys/sysmacros.h> @@ -389,6 +387,10 @@ memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg, int attr, int mask) return (error); } break; + case MC_INHERIT_ZERO: + if (arg != 0 || attr != NULL || mask != 0) + return (set_errno(EINVAL)); + break; default: return (set_errno(EINVAL)); } diff --git a/usr/src/uts/common/vm/seg.h b/usr/src/uts/common/vm/seg.h index 2e1e6a77de..343e308a82 100644 --- a/usr/src/uts/common/vm/seg.h +++ b/usr/src/uts/common/vm/seg.h @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2015, Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -39,8 +40,6 @@ #ifndef _VM_SEG_H #define _VM_SEG_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/vnode.h> #include <sys/avl.h> #include <vm/seg_enum.h> @@ -142,6 +141,7 @@ struct seg_ops { int (*getmemid)(struct seg *, caddr_t, memid_t *); struct lgrp_mem_policy_info *(*getpolicy)(struct seg *, caddr_t); int (*capable)(struct seg *, segcapability_t); + int (*inherit)(struct seg *, caddr_t, size_t, uint_t); }; #ifdef _KERNEL @@ -238,6 +238,7 @@ extern segadvstat_t segadvstat; #define SEGOP_GETMEMID(s, a, mp) (*(s)->s_ops->getmemid)((s), (a), (mp)) #define SEGOP_GETPOLICY(s, a) (*(s)->s_ops->getpolicy)((s), (a)) #define SEGOP_CAPABLE(s, c) (*(s)->s_ops->capable)((s), (c)) +#define SEGOP_INHERIT(s, a, l, b) (*(s)->s_ops->inherit)((s), (a), (l), (b)) #define seg_page(seg, addr) \ (((uintptr_t)((addr) - (seg)->s_base)) >> PAGESHIFT) @@ -249,6 +250,11 @@ extern segadvstat_t segadvstat; #define IE_RETRY -2 /* internal to seg layer */ #define IE_REATTACH -3 /* internal to seg layer */ +/* Values for SEGOP_INHERIT */ +#define SEGP_INH_ZERO 0x01 + +int seg_inherit_notsup(struct seg *, caddr_t, size_t, uint_t); + /* Delay/retry factors for seg_p_mem_config_pre_del */ #define SEGP_PREDEL_DELAY_FACTOR 4 /* diff --git a/usr/src/uts/common/vm/seg_dev.c b/usr/src/uts/common/vm/seg_dev.c index 9d214024a5..6cf938a007 100644 --- a/usr/src/uts/common/vm/seg_dev.c +++ b/usr/src/uts/common/vm/seg_dev.c @@ -215,6 +215,7 @@ struct seg_ops segdev_ops = { segdev_getmemid, segdev_getpolicy, segdev_capable, + seg_inherit_notsup }; /* diff --git a/usr/src/uts/common/vm/seg_kmem.c b/usr/src/uts/common/vm/seg_kmem.c index 205aac9ded..90e1b73b70 100644 --- a/usr/src/uts/common/vm/seg_kmem.c +++ b/usr/src/uts/common/vm/seg_kmem.c @@ -797,6 +797,7 @@ static struct seg_ops segkmem_ops = { segkmem_getmemid, segkmem_getpolicy, /* getpolicy */ segkmem_capable, /* capable */ + seg_inherit_notsup /* inherit */ }; int diff --git a/usr/src/uts/common/vm/seg_kp.c b/usr/src/uts/common/vm/seg_kp.c index 2fe1e5f17d..d33ff004f1 100644 --- a/usr/src/uts/common/vm/seg_kp.c +++ b/usr/src/uts/common/vm/seg_kp.c @@ -169,6 +169,7 @@ static struct seg_ops segkp_ops = { segkp_getmemid, /* getmemid */ segkp_getpolicy, /* getpolicy */ segkp_capable, /* capable */ + seg_inherit_notsup /* inherit */ }; diff --git a/usr/src/uts/common/vm/seg_kpm.c b/usr/src/uts/common/vm/seg_kpm.c index 4f764588b1..0886513183 100644 --- a/usr/src/uts/common/vm/seg_kpm.c +++ b/usr/src/uts/common/vm/seg_kpm.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Kernel Physical Mapping (kpm) segment driver (segkpm). * @@ -136,6 +134,7 @@ static struct seg_ops segkpm_ops = { SEGKPM_BADOP(int), /* getmemid */ SEGKPM_BADOP(lgrp_mem_policy_info_t *), /* getpolicy */ segkpm_capable, /* capable */ + seg_inherit_notsup /* inherit */ }; /* @@ -160,8 +159,8 @@ segkpm_create(struct seg *seg, void *argsp) ASSERT(seg->s_as && RW_WRITE_HELD(&seg->s_as->a_lock)); ASSERT(btokpmp(seg->s_size) >= 1 && - kpmpageoff((uintptr_t)seg->s_base) == 0 && - kpmpageoff((uintptr_t)seg->s_base + seg->s_size) == 0); + kpmpageoff((uintptr_t)seg->s_base) == 0 && + kpmpageoff((uintptr_t)seg->s_base + seg->s_size) == 0); skd = kmem_zalloc(sizeof (struct segkpm_data), KM_SLEEP); @@ -193,7 +192,7 @@ segkpm_create(struct seg *seg, void *argsp) skd->skd_nvcolors = b->nvcolors; p = skd->skd_va_select = - kmem_zalloc(NCPU * b->nvcolors * sizeof (ushort_t), KM_SLEEP); + kmem_zalloc(NCPU * b->nvcolors * sizeof (ushort_t), KM_SLEEP); for (i = 0; i < NCPU; i++) for (j = 0; j < b->nvcolors; j++, p++) diff --git a/usr/src/uts/common/vm/seg_map.c b/usr/src/uts/common/vm/seg_map.c index a57d202a6a..1edb92e892 100644 --- a/usr/src/uts/common/vm/seg_map.c +++ b/usr/src/uts/common/vm/seg_map.c @@ -124,6 +124,7 @@ static struct seg_ops segmap_ops = { segmap_getmemid, /* getmemid */ segmap_getpolicy, /* getpolicy */ segmap_capable, /* capable */ + seg_inherit_notsup /* inherit */ }; /* diff --git a/usr/src/uts/common/vm/seg_spt.c b/usr/src/uts/common/vm/seg_spt.c index f087d5fc30..8d85fbaef7 100644 --- a/usr/src/uts/common/vm/seg_spt.c +++ b/usr/src/uts/common/vm/seg_spt.c @@ -109,6 +109,7 @@ struct seg_ops segspt_ops = { SEGSPT_BADOP(int), /* getmemid */ segspt_getpolicy, /* getpolicy */ SEGSPT_BADOP(int), /* capable */ + seg_inherit_notsup /* inherit */ }; static int segspt_shmdup(struct seg *seg, struct seg *newseg); @@ -168,6 +169,7 @@ struct seg_ops segspt_shmops = { segspt_shmgetmemid, segspt_shmgetpolicy, segspt_shmcapable, + seg_inherit_notsup }; static void segspt_purge(struct seg *seg); diff --git a/usr/src/uts/common/vm/seg_vn.c b/usr/src/uts/common/vm/seg_vn.c index 0e07ce22f5..b33832c157 100644 --- a/usr/src/uts/common/vm/seg_vn.c +++ b/usr/src/uts/common/vm/seg_vn.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 1986, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014, Joyent, Inc. All rights reserved. + * Copyright 2015, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -113,6 +113,7 @@ static int segvn_getmemid(struct seg *seg, caddr_t addr, memid_t *memidp); static lgrp_mem_policy_info_t *segvn_getpolicy(struct seg *, caddr_t); static int segvn_capable(struct seg *seg, segcapability_t capable); +static int segvn_inherit(struct seg *, caddr_t, size_t, uint_t); struct seg_ops segvn_ops = { segvn_dup, @@ -138,6 +139,7 @@ struct seg_ops segvn_ops = { segvn_getmemid, segvn_getpolicy, segvn_capable, + segvn_inherit }; /* @@ -807,6 +809,7 @@ segvn_create(struct seg *seg, void *argsp) svd->softlockcnt = 0; svd->softlockcnt_sbase = 0; svd->softlockcnt_send = 0; + svd->svn_inz = 0; svd->rcookie = HAT_INVALID_REGION_COOKIE; svd->pageswap = 0; @@ -1465,6 +1468,81 @@ segvn_extend_next( return (0); } +/* + * Duplicate all the pages in the segment. This may break COW sharing for a + * given page. If the page is marked with inherit zero set, then instead of + * duplicating the page, we zero the page. + */ +static int +segvn_dup_pages(struct seg *seg, struct seg *newseg) +{ + int error; + uint_t prot; + page_t *pp; + struct anon *ap, *newap; + size_t i; + caddr_t addr; + + struct segvn_data *svd = (struct segvn_data *)seg->s_data; + struct segvn_data *newsvd = (struct segvn_data *)newseg->s_data; + ulong_t old_idx = svd->anon_index; + ulong_t new_idx = 0; + + i = btopr(seg->s_size); + addr = seg->s_base; + + /* + * XXX break cow sharing using PAGESIZE + * pages. They will be relocated into larger + * pages at fault time. + */ + while (i-- > 0) { + if ((ap = anon_get_ptr(svd->amp->ahp, old_idx)) != NULL) { + struct vpage *vpp; + + vpp = &svd->vpage[seg_page(seg, addr)]; + + /* + * prot need not be computed below 'cause anon_private + * is going to ignore it anyway as child doesn't inherit + * pagelock from parent. + */ + prot = svd->pageprot ? VPP_PROT(vpp) : svd->prot; + + /* + * Check whether we should zero this or dup it. + */ + if (svd->svn_inz == SEGVN_INZ_ALL || + (svd->svn_inz == SEGVN_INZ_VPP && + VPP_ISINHZERO(vpp))) { + pp = anon_zero(newseg, addr, &newap, + newsvd->cred); + } else { + page_t *anon_pl[1+1]; + uint_t vpprot; + error = anon_getpage(&ap, &vpprot, anon_pl, + PAGESIZE, seg, addr, S_READ, svd->cred); + if (error != 0) + return (error); + + pp = anon_private(&newap, newseg, addr, prot, + anon_pl[0], 0, newsvd->cred); + } + if (pp == NULL) { + return (ENOMEM); + } + (void) anon_set_ptr(newsvd->amp->ahp, new_idx, newap, + ANON_SLEEP); + page_unlock(pp); + } + addr += PAGESIZE; + old_idx++; + new_idx++; + } + + return (0); +} + static int segvn_dup(struct seg *seg, struct seg *newseg) { @@ -1472,7 +1550,6 @@ segvn_dup(struct seg *seg, struct seg *newseg) struct segvn_data *newsvd; pgcnt_t npages = seg_pages(seg); int error = 0; - uint_t prot; size_t len; struct anon_map *amp; @@ -1516,6 +1593,7 @@ segvn_dup(struct seg *seg, struct seg *newseg) crhold(newsvd->cred); newsvd->advice = svd->advice; newsvd->pageadvice = svd->pageadvice; + newsvd->svn_inz = svd->svn_inz; newsvd->swresv = svd->swresv; newsvd->pageswap = svd->pageswap; newsvd->flags = svd->flags; @@ -1545,6 +1623,7 @@ segvn_dup(struct seg *seg, struct seg *newseg) ASSERT(svd->tr_state == SEGVN_TR_OFF); newsvd->tr_state = SEGVN_TR_OFF; if (svd->type == MAP_SHARED) { + ASSERT(svd->svn_inz == SEGVN_INZ_NONE); newsvd->amp = amp; ANON_LOCK_ENTER(&->a_rwlock, RW_WRITER); amp->refcnt++; @@ -1560,6 +1639,9 @@ segvn_dup(struct seg *seg, struct seg *newseg) ANON_SLEEP); newsvd->amp->a_szc = newseg->s_szc; newsvd->anon_index = 0; + ASSERT(svd->svn_inz == SEGVN_INZ_NONE || + svd->svn_inz == SEGVN_INZ_ALL || + svd->svn_inz == SEGVN_INZ_VPP); /* * We don't have to acquire the anon_map lock @@ -1583,17 +1665,16 @@ segvn_dup(struct seg *seg, struct seg *newseg) * The strategy here is to just break the * sharing on pages that could possibly be * softlocked. + * + * In addition, if any pages have been marked that they + * should be inherited as zero, then we immediately go + * ahead and break COW and zero them. In the case of a + * softlocked page that should be inherited zero, we + * break COW and just get a zero page. */ retry: - if (svd->softlockcnt) { - struct anon *ap, *newap; - size_t i; - uint_t vpprot; - page_t *anon_pl[1+1], *pp; - caddr_t addr; - ulong_t old_idx = svd->anon_index; - ulong_t new_idx = 0; - + if (svd->softlockcnt || + svd->svn_inz != SEGVN_INZ_NONE) { /* * The softlock count might be non zero * because some pages are still stuck in the @@ -1603,59 +1684,16 @@ retry: * pages]. Note, we have the writers lock so * nothing gets inserted during the flush. */ - if (reclaim == 1) { + if (svd->softlockcnt && reclaim == 1) { segvn_purge(seg); reclaim = 0; goto retry; } - i = btopr(seg->s_size); - addr = seg->s_base; - /* - * XXX break cow sharing using PAGESIZE - * pages. They will be relocated into larger - * pages at fault time. - */ - while (i-- > 0) { - if (ap = anon_get_ptr(amp->ahp, - old_idx)) { - error = anon_getpage(&ap, - &vpprot, anon_pl, PAGESIZE, - seg, addr, S_READ, - svd->cred); - if (error) { - newsvd->vpage = NULL; - goto out; - } - /* - * prot need not be computed - * below 'cause anon_private is - * going to ignore it anyway - * as child doesn't inherit - * pagelock from parent. - */ - prot = svd->pageprot ? - VPP_PROT( - &svd->vpage[ - seg_page(seg, addr)]) - : svd->prot; - pp = anon_private(&newap, - newseg, addr, prot, - anon_pl[0], 0, - newsvd->cred); - if (pp == NULL) { - /* no mem abort */ - newsvd->vpage = NULL; - error = ENOMEM; - goto out; - } - (void) anon_set_ptr( - newsvd->amp->ahp, new_idx, - newap, ANON_SLEEP); - page_unlock(pp); - } - addr += PAGESIZE; - old_idx++; - new_idx++; + + error = segvn_dup_pages(seg, newseg); + if (error != 0) { + newsvd->vpage = NULL; + goto out; } } else { /* common case */ if (seg->s_szc != 0) { @@ -2192,6 +2230,7 @@ retry: nsvd->softlockcnt = 0; nsvd->softlockcnt_sbase = 0; nsvd->softlockcnt_send = 0; + nsvd->svn_inz = svd->svn_inz; ASSERT(nsvd->rcookie == HAT_INVALID_REGION_COOKIE); if (svd->vp != NULL) { @@ -8004,7 +8043,7 @@ out: /* * Set advice from user for specified pages - * There are 5 types of advice: + * There are 9 types of advice: * MADV_NORMAL - Normal (default) behavior (whatever that is) * MADV_RANDOM - Random page references * do not allow readahead or 'klustering' @@ -8486,6 +8525,81 @@ segvn_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav) } /* + * There is one kind of inheritance that can be specified for pages: + * + * SEGP_INH_ZERO - Pages should be zeroed in the child + */ +static int +segvn_inherit(struct seg *seg, caddr_t addr, size_t len, uint_t behav) +{ + struct segvn_data *svd = (struct segvn_data *)seg->s_data; + struct vpage *bvpp, *evpp; + size_t page; + int ret = 0; + + ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as, &seg->s_as->a_lock)); + + /* Can't support something we don't know about */ + if (behav != SEGP_INH_ZERO) + return (ENOTSUP); + + SEGVN_LOCK_ENTER(seg->s_as, &svd->lock, RW_WRITER); + + /* + * This must be a straightforward anonymous segment that is mapped + * privately and is not backed by a vnode. + */ + if (svd->tr_state != SEGVN_TR_OFF || + svd->type != MAP_PRIVATE || + svd->vp != NULL) { + ret = EINVAL; + goto out; + } + + /* + * If the entire segment has been marked as inherit zero, then no reason + * to do anything else. + */ + if (svd->svn_inz == SEGVN_INZ_ALL) { + ret = 0; + goto out; + } + + /* + * If this applies to the entire segment, simply mark it and we're done. + */ + if ((addr == seg->s_base) && (len == seg->s_size)) { + svd->svn_inz = SEGVN_INZ_ALL; + ret = 0; + goto out; + } + + /* + * We've been asked to mark a subset of this segment as inherit zero, + * therefore we need to mainpulate its vpages. + */ + if (svd->vpage == NULL) { + segvn_vpage(seg); + if (svd->vpage == NULL) { + ret = ENOMEM; + goto out; + } + } + + svd->svn_inz = SEGVN_INZ_VPP; + page = seg_page(seg, addr); + bvpp = &svd->vpage[page]; + evpp = &svd->vpage[page + (len >> PAGESHIFT)]; + for (; bvpp < evpp; bvpp++) + VPP_SETINHZERO(bvpp); + ret = 0; + +out: + SEGVN_LOCK_EXIT(seg->s_as, &svd->lock); + return (ret); +} + +/* * Create a vpage structure for this seg. */ static void diff --git a/usr/src/uts/common/vm/seg_vn.h b/usr/src/uts/common/vm/seg_vn.h index f94e0cb873..51ebda3a84 100644 --- a/usr/src/uts/common/vm/seg_vn.h +++ b/usr/src/uts/common/vm/seg_vn.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -98,6 +99,7 @@ typedef struct segvn_data { size_t swresv; /* swap space reserved for this segment */ uchar_t advice; /* madvise flags for segment */ uchar_t pageadvice; /* true if per page advice set */ + uchar_t svn_inz; /* true if pages marked as inherit zero */ ushort_t flags; /* flags - from sys/mman.h */ spgcnt_t softlockcnt; /* # of pages SOFTLOCKED in seg */ lgrp_mem_policy_info_t policy_info; /* memory allocation policy */ @@ -122,6 +124,13 @@ typedef struct segvn_data { #define SEGVN_TR_OFF (2) /* Text replication is disabled */ /* + * Inherit zero states + */ +#define SEGVN_INZ_NONE (0) /* Nothing in the segment is inherit zero */ +#define SEGVN_INZ_ALL (1) /* Everything in the segment is inherit zero */ +#define SEGVN_INZ_VPP (2) /* Check struct vpages for inherit zero */ + +/* * Macros for segvn segment driver locking. */ #define SEGVN_LOCK_ENTER(as, lock, type) rw_enter((lock), (type)) diff --git a/usr/src/uts/common/vm/vm_as.c b/usr/src/uts/common/vm/vm_as.c index 8caa257486..992254938f 100644 --- a/usr/src/uts/common/vm/vm_as.c +++ b/usr/src/uts/common/vm/vm_as.c @@ -21,7 +21,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2012, Joyent, Inc. All rights reserved. + * Copyright 2015, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -2566,6 +2566,19 @@ retry: } break; + case MC_INHERIT_ZERO: + if (seg->s_ops->inherit == NULL) { + error = ENOTSUP; + } else { + error = SEGOP_INHERIT(seg, raddr, ssize, + SEGP_INH_ZERO); + } + if (error != 0) { + AS_LOCK_EXIT(as, &as->a_lock); + return (error); + } + break; + /* * Can't happen. */ diff --git a/usr/src/uts/common/vm/vm_seg.c b/usr/src/uts/common/vm/vm_seg.c index 65c6c5ecdc..e54401ddeb 100644 --- a/usr/src/uts/common/vm/vm_seg.c +++ b/usr/src/uts/common/vm/vm_seg.c @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2015, Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -1851,3 +1852,13 @@ seg_swresv(struct seg *seg) } return (swap); } + +/* + * General not supported function for SEGOP_INHERIT + */ +/* ARGSUSED */ +int +seg_inherit_notsup(struct seg *seg, caddr_t addr, size_t len, uint_t op) +{ + return (ENOTSUP); +} diff --git a/usr/src/uts/common/vm/vpage.h b/usr/src/uts/common/vm/vpage.h index 368bc629ff..5eaefb9738 100644 --- a/usr/src/uts/common/vm/vpage.h +++ b/usr/src/uts/common/vm/vpage.h @@ -21,6 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -39,8 +40,6 @@ #ifndef _VM_VPAGE_H #define _VM_VPAGE_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -57,9 +56,10 @@ struct vpage { * This was changed from a bitfield to flags/macros in order * to conserve space (uchar_t bitfields are not ANSI). This could * have been condensed to a uchar_t, but at the expense of complexity. - * We've stolen two bits from the top of nvp_advice: the first to store - * pplock, and the second to identify pages for which we have reserved - * swap space, but have not necessarily allocated anon slots. + * We've stolen three bits from the top of nvp_advice: the first to store + * pplock, the second to identify pages for which we have reserved + * swap space, but have not necessarily allocated anon slots, and the third to + * indicate that the page should be zeroed on fork. * * WARNING: VPP_SETADVICE(vpp, x) evaluates vpp twice, and VPP_PLOCK(vpp) * returns a positive integer when the lock is held, not necessarily (1). @@ -69,6 +69,7 @@ struct vpage { #define VP_PPLOCK_SHIFT (0x07) /* offset of lock hiding inside nvp_advice */ #define VP_SWAPRES_MASK (0x40) /* Swap space has been reserved, but we */ /* might not have allocated an anon slot */ +#define VP_INHZERO_MASK (0x20) /* zero page on fork() */ #define VPP_PROT(vpp) ((vpp)->nvp_prot) #define VPP_ADVICE(vpp) ((vpp)->nvp_advice & VP_ADVICE_MASK) @@ -76,6 +77,8 @@ struct vpage { ((uchar_t)((vpp)->nvp_advice & VP_PPLOCK_MASK)) #define VPP_ISSWAPRES(vpp) \ ((uchar_t)((vpp)->nvp_advice & VP_SWAPRES_MASK)) +#define VPP_ISINHZERO(vpp) \ + ((uchar_t)((vpp)->nvp_advice & VP_INHZERO_MASK)) #define VPP_SETPROT(vpp, x) ((vpp)->nvp_prot = (x)) #define VPP_SETADVICE(vpp, x) \ @@ -85,6 +88,8 @@ struct vpage { #define VPP_CLRPPLOCK(vpp) ((vpp)->nvp_advice &= ~VP_PPLOCK_MASK) #define VPP_SETSWAPRES(vpp) ((vpp)->nvp_advice |= VP_SWAPRES_MASK) #define VPP_CLRSWAPRES(vpp) ((vpp)->nvp_advice &= ~VP_SWAPRES_MASK) +#define VPP_SETINHZERO(vpp) ((vpp)->nvp_advice |= VP_INHZERO_MASK) +#define VPP_CLRINHZERO(vpp) ((vpp)->nvp_advice &= ~VP_INHZERO_MASK) #ifdef __cplusplus } diff --git a/usr/src/uts/i86xpv/vm/seg_mf.c b/usr/src/uts/i86xpv/vm/seg_mf.c index df2fe17e18..081ee85b15 100644 --- a/usr/src/uts/i86xpv/vm/seg_mf.c +++ b/usr/src/uts/i86xpv/vm/seg_mf.c @@ -780,5 +780,6 @@ static struct seg_ops segmf_ops = { segmf_setpagesize, segmf_getmemid, segmf_getpolicy, - segmf_capable + segmf_capable, + seg_inherit_notsup }; diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s index 43d7ce16e1..642704436a 100644 --- a/usr/src/uts/intel/ia32/ml/modstubs.s +++ b/usr/src/uts/intel/ia32/ml/modstubs.s @@ -21,7 +21,7 @@ /* * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ #include <sys/asm_linkage.h> @@ -1228,6 +1228,7 @@ fcnname/**/_info: \ NO_UNLOAD_STUB(kcf, crypto_verify_recover_init_prov, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_add_entropy, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_add_pseudo_entropy, nomod_minus_one); + NO_UNLOAD_STUB(kcf, random_get_blocking_bytes, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_get_bytes, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_get_pseudo_bytes, nomod_minus_one); END_MODULE(kcf); diff --git a/usr/src/uts/intel/os/name_to_sysnum b/usr/src/uts/intel/os/name_to_sysnum index eed990a8da..e15d36bf94 100644 --- a/usr/src/uts/intel/os/name_to_sysnum +++ b/usr/src/uts/intel/os/name_to_sysnum @@ -117,6 +117,7 @@ readv 121 writev 122 preadv 123 pwritev 124 +getrandom 126 mmapobj 127 setrlimit 128 getrlimit 129 diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s index 67a0269ceb..d64bdd4d01 100644 --- a/usr/src/uts/sparc/ml/modstubs.s +++ b/usr/src/uts/sparc/ml/modstubs.s @@ -20,7 +20,7 @@ */ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2015, Joyent, Inc. All rights reserved. */ #if !defined(lint) @@ -1151,6 +1151,7 @@ stubs_base: NO_UNLOAD_STUB(kcf, crypto_verify_recover_init_prov, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_add_entropy, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_add_pseudo_entropy, nomod_minus_one); + NO_UNLOAD_STUB(kcf, random_get_blocking_bytes, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_get_bytes, nomod_minus_one); NO_UNLOAD_STUB(kcf, random_get_pseudo_bytes, nomod_minus_one); END_MODULE(kcf); diff --git a/usr/src/uts/sparc/os/name_to_sysnum b/usr/src/uts/sparc/os/name_to_sysnum index a762ee1c65..2ad65cc7ba 100644 --- a/usr/src/uts/sparc/os/name_to_sysnum +++ b/usr/src/uts/sparc/os/name_to_sysnum @@ -115,6 +115,7 @@ readv 121 writev 122 preadv 123 pwritev 124 +getrandom 126 mmapobj 127 setrlimit 128 getrlimit 129 |