diff --git a/include/unistd.h b/include/unistd.h index 0329122..40ed78e 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -581,6 +581,7 @@ off_t __syscall(quad_t, ...); int undelete(const char *); int unwhiteout(const char *); void *valloc(size_t); /* obsoleted by malloc() */ +int getentropy(void *, size_t); #ifndef _OPTRESET_DECLARED #define _OPTRESET_DECLARED diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 07a4537..e5022ab 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -123,6 +123,7 @@ MAN+= abort2.2 \ fsync.2 \ getdirentries.2 \ getdtablesize.2 \ + getentropy.2 \ getfh.2 \ getfsstat.2 \ getgid.2 \ diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index fe887c3..ea86e81 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -393,6 +393,7 @@ FBSD_1.3 { ffclock_getcounter; ffclock_getestimate; ffclock_setestimate; + getentropy; pipe2; posix_fadvise; procctl; @@ -612,6 +613,8 @@ FBSDprivate_1.0 { _getegid; __sys_getegid; _geteuid; + __sys_getentropy; + _getentropy; __sys_geteuid; _getfh; __sys_getfh; diff --git a/lib/libc/sys/getentropy.2 b/lib/libc/sys/getentropy.2 new file mode 100644 index 0000000..94f4f4e --- /dev/null +++ b/lib/libc/sys/getentropy.2 @@ -0,0 +1,69 @@ +.\" $OpenBSD: getentropy.2,v 1.6 2014/07/18 18:20:17 deraadt 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. +.\" +.Dd $Mdocdate: July 18 2014 $ +.Dt GETENTROPY 2 +.Os +.Sh NAME +.Nm getentropy +.Nd get entropy +.Sh SYNOPSIS +.Fd #include +.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 3 . +.Pp +The maximum buffer size permitted is 256 bytes. +Even if +.Va buflen +exceeds this. +.Pp +.Nm +is not intended for regular code; please use the +.Xr arc4random 3 +family of functions instead. +.Sh RETURN VALUES +Upon successful completion, a value of 0 is returned. +Otherwise, a value of \-1 is returned and +.Va errno +is set to indicate the error. +.Sh ERRORS +.Fn getentropy +will succeed unless: +.Bl -tag -width Er +.It Bq Er EFAULT +The +.Fa buf +parameter points to an +invalid address. +.El +.It Bq Er EIO +Too +.Fa many bytes +requested, or some other +fatal error occurred. +.El +.Sh SEE ALSO +.Xr arc4random 3 +.Sh HISTORY +The +.Nm +function appeared in +.Ox 5.6 . diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index e627ff3..58ea92c 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -452,4 +452,5 @@ #define FREEBSD32_SYS_freebsd32_aio_mlock 543 #define FREEBSD32_SYS_freebsd32_procctl 544 #define FREEBSD32_SYS_freebsd32_procctl 544 -#define FREEBSD32_SYS_MAXSYSCALL 545 +#define FREEBSD32_SYS_getentropy 545 +#define FREEBSD32_SYS_MAXSYSCALL 546 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index 2bf45ea..d0a732e 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -578,4 +578,5 @@ const char *freebsd32_syscallnames[] = { #else "freebsd32_procctl", /* 544 = freebsd32_procctl */ #endif + "getentropy", /* 545 = getentropy */ }; diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 9735e30..6fe0c9e 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -615,4 +615,5 @@ struct sysent freebsd32_sysent[] = { #else { AS(freebsd32_procctl_args), (sy_call_t *)freebsd32_procctl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 544 = freebsd32_procctl */ #endif + { AS(getentropy_args), (sy_call_t *)sys_getentropy, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 545 = getentropy */ }; diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index db03855..48793a2 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -3299,6 +3299,14 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) break; } #endif + /* getentropy */ + case 545: { + struct getentropy_args *p = params; + uarg[0] = (intptr_t) p->ptr; /* void * */ + uarg[1] = p->len; /* size_t */ + *n_args = 2; + break; + } default: *n_args = 0; break; @@ -8844,6 +8852,19 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) }; break; #endif + /* getentropy */ + case 545: + switch(ndx) { + case 0: + p = "void *"; + break; + case 1: + p = "size_t"; + break; + default: + break; + }; + break; default: break; }; @@ -10717,6 +10738,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) p = "int"; break; #endif + /* getentropy */ + case 545: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 2fafc0c..e97d537a 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -1066,3 +1066,5 @@ uint32_t id1, uint32_t id2, int com, \ void *data); } #endif +545 AUE_NULL NOPROTO { int getentropy(void *ptr, \ + size_t len); } diff --git a/sys/conf/files b/sys/conf/files index e3820f3..3898c8b 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3068,6 +3068,7 @@ kern/sys_pipe.c standard kern/sys_procdesc.c standard kern/sys_process.c standard kern/sys_socket.c standard +kern/sys_random.c standard kern/syscalls.c standard kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 3decfd4..eb20547 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -579,4 +579,5 @@ struct sysent sysent[] = { { AS(pipe2_args), (sy_call_t *)sys_pipe2, AUE_PIPE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 542 = pipe2 */ { AS(aio_mlock_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 543 = aio_mlock */ { AS(procctl_args), (sy_call_t *)sys_procctl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 544 = procctl */ + { AS(getentropy_args), (sy_call_t *)sys_getentropy, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 545 = getentropy */ }; diff --git a/sys/kern/sys_random.c b/sys/kern/sys_random.c new file mode 100644 index 0000000..dc860da --- /dev/null +++ b/sys/kern/sys_random.c @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2014, by Theo de Raadt + * 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. 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. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#ifndef _SYS_SYSPROTO_H_ +struct getentropy_args { + void *ptr; + size_t len; +}; +#endif + +int +sys_getentropy(struct thread *td, struct getentropy_args *uap) +{ + char buf[256]; + int error; + + if (uap->len > sizeof(buf)) + return (EIO); + + arc4rand(buf, uap->len, 1); + if ((error = copyout(buf, uap->ptr, uap->len)) != 0) + return (error); + + explicit_bzero(buf, sizeof(buf)); + + return (0); +} diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 276c34a..4b74333 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -552,4 +552,5 @@ const char *syscallnames[] = { "pipe2", /* 542 = pipe2 */ "aio_mlock", /* 543 = aio_mlock */ "procctl", /* 544 = procctl */ + "getentropy", /* 545 = getentropy */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 35c05f0..8fcb562 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -980,5 +980,6 @@ 543 AUE_NULL NOSTD { int aio_mlock(struct aiocb *aiocbp); } 544 AUE_NULL STD { int procctl(idtype_t idtype, id_t id, \ int com, void *data); } +545 AUE_NULL STD { int getentropy(void *ptr, size_t len); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index ce2be6d..d229f96 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -3372,6 +3372,14 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 4; break; } + /* getentropy */ + case 545: { + struct getentropy_args *p = params; + uarg[0] = (intptr_t) p->ptr; /* void * */ + uarg[1] = p->len; /* size_t */ + *n_args = 2; + break; + } default: *n_args = 0; break; @@ -8990,6 +8998,19 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; + /* getentropy */ + case 545: + switch(ndx) { + case 0: + p = "void *"; + break; + case 1: + p = "size_t"; + break; + default: + break; + }; + break; default: break; }; @@ -10928,6 +10949,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; + /* getentropy */ + case 545: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index 576b420..0ad780c 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -462,4 +462,5 @@ #define SYS_pipe2 542 #define SYS_aio_mlock 543 #define SYS_procctl 544 -#define SYS_MAXSYSCALL 545 +#define SYS_getentropy 545 +#define SYS_MAXSYSCALL 546 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 47d2046..49f9401 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -409,4 +409,5 @@ MIASM = \ accept4.o \ pipe2.o \ aio_mlock.o \ - procctl.o + procctl.o \ + getentropy.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 3d203ad..cd152a5 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -1813,6 +1813,10 @@ struct procctl_args { char com_l_[PADL_(int)]; int com; char com_r_[PADR_(int)]; char data_l_[PADL_(void *)]; void * data; char data_r_[PADR_(void *)]; }; +struct getentropy_args { + char ptr_l_[PADL_(void *)]; void * ptr; char ptr_r_[PADR_(void *)]; + char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2204,6 +2208,7 @@ int sys_accept4(struct thread *, struct accept4_args *); int sys_pipe2(struct thread *, struct pipe2_args *); int sys_aio_mlock(struct thread *, struct aio_mlock_args *); int sys_procctl(struct thread *, struct procctl_args *); +int sys_getentropy(struct thread *, struct getentropy_args *); #ifdef COMPAT_43 @@ -2909,6 +2914,7 @@ int freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *); #define SYS_AUE_pipe2 AUE_PIPE #define SYS_AUE_aio_mlock AUE_NULL #define SYS_AUE_procctl AUE_NULL +#define SYS_AUE_getentropy AUE_NULL #undef PAD_ #undef PADL_