freebsd-dev/sys/kern/sys_getrandom.c
Brooks Davis 6469bdcdb6 Move most of the contents of opt_compat.h to opt_global.h.
opt_compat.h is mentioned in nearly 180 files. In-progress network
driver compabibility improvements may add over 100 more so this is
closer to "just about everywhere" than "only some files" per the
guidance in sys/conf/options.

Keep COMPAT_LINUX32 in opt_compat.h as it is confined to a subset of
sys/compat/linux/*.c.  A fake _COMPAT_LINUX option ensure opt_compat.h
is created on all architectures.

Move COMPAT_LINUXKPI to opt_dontuse.h as it is only used to control the
set of compiled files.

Reviewed by:	kib, cem, jhb, jtl
Sponsored by:	DARPA, AFRL
Differential Revision:	https://reviews.freebsd.org/D14941
2018-04-06 17:35:35 +00:00

97 lines
2.8 KiB
C

/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/limits.h>
#include <sys/proc.h>
#include <sys/random.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/uio.h>
#define GRND_VALIDFLAGS (GRND_NONBLOCK | GRND_RANDOM)
/*
* random_read_uio(9) returns EWOULDBLOCK if a nonblocking request would block,
* but the Linux API name is EAGAIN. On FreeBSD, they have the same numeric
* value for now.
*/
CTASSERT(EWOULDBLOCK == EAGAIN);
static int
kern_getrandom(struct thread *td, void *user_buf, size_t buflen,
unsigned int flags)
{
struct uio auio;
struct iovec aiov;
int error;
if ((flags & ~GRND_VALIDFLAGS) != 0)
return (EINVAL);
if (buflen > IOSIZE_MAX)
return (EINVAL);
if (buflen == 0) {
td->td_retval[0] = 0;
return (0);
}
aiov.iov_base = user_buf;
aiov.iov_len = buflen;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_resid = buflen;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_rw = UIO_READ;
auio.uio_td = td;
error = read_random_uio(&auio, (flags & GRND_NONBLOCK) != 0);
if (error == 0)
td->td_retval[0] = buflen - auio.uio_resid;
return (error);
}
#ifndef _SYS_SYSPROTO_H_
struct getrandom_args {
void *buf;
size_t buflen;
unsigned int flags;
};
#endif
int
sys_getrandom(struct thread *td, struct getrandom_args *uap)
{
return (kern_getrandom(td, uap->buf, uap->buflen, uap->flags));
}