Module Name: src Committed By: apb Date: Mon Dec 19 21:53:52 UTC 2011
Modified Files: src/sys/compat/common: Makefile src/sys/dev: rndpseudo.c Added Files: src/sys/compat/common: rndpseudo_50.c src/sys/compat/sys: rnd.h Log Message: Add COMPAT_50 and COMPAT_NETBSD32 compatibility code for rnd(4) ioctl commands. Tested with "rndctl -ls" using an old 32-bit version of rndctl(8) (built for NetBSD-5.99.56/i386) and a new 64-bit kernel (NetBSD-5.99.59/amd64). To generate a diff of this commit: cvs rdiff -u -r1.47 -r1.48 src/sys/compat/common/Makefile cvs rdiff -u -r0 -r1.1 src/sys/compat/common/rndpseudo_50.c cvs rdiff -u -r0 -r1.1 src/sys/compat/sys/rnd.h cvs rdiff -u -r1.3 -r1.4 src/sys/dev/rndpseudo.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/compat/common/Makefile diff -u src/sys/compat/common/Makefile:1.47 src/sys/compat/common/Makefile:1.48 --- src/sys/compat/common/Makefile:1.47 Thu Aug 11 21:23:09 2011 +++ src/sys/compat/common/Makefile Mon Dec 19 21:53:52 2011 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.47 2011/08/11 21:23:09 jmcneill Exp $ +# $NetBSD: Makefile,v 1.48 2011/12/19 21:53:52 apb Exp $ LIB= compat NOPIC= # defined @@ -40,9 +40,9 @@ SRCS+= kern_time_30.c vfs_syscalls_30.c SRCS+= vfs_syscalls_40.c uipc_syscalls_40.c # Compatibility code for NetBSD 5.0 -SRCS+= kern_time_50.c kern_select_50.c rtsock_50.c sysv_msg_50.c \ - sysv_sem_50.c sysv_shm_50.c vfs_syscalls_50.c uipc_syscalls_50.c \ - sysv_ipc_50.c +SRCS+= kern_time_50.c kern_select_50.c rndpseudo_50.c rtsock_50.c \ + sysv_ipc_50.c sysv_msg_50.c sysv_sem_50.c sysv_shm_50.c \ + vfs_syscalls_50.c uipc_syscalls_50.c # really, all machines where sizeof(int) != sizeof(long) (LP64) .if (${MACHINE_ARCH} != "alpha" && ${MACHINE_ARCH} != "sparc64" \ Index: src/sys/dev/rndpseudo.c diff -u src/sys/dev/rndpseudo.c:1.3 src/sys/dev/rndpseudo.c:1.4 --- src/sys/dev/rndpseudo.c:1.3 Mon Dec 19 21:44:08 2011 +++ src/sys/dev/rndpseudo.c Mon Dec 19 21:53:52 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: rndpseudo.c,v 1.3 2011/12/19 21:44:08 apb Exp $ */ +/* $NetBSD: rndpseudo.c,v 1.4 2011/12/19 21:53:52 apb Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -30,7 +30,11 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.3 2011/12/19 21:44:08 apb Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.4 2011/12/19 21:53:52 apb Exp $"); + +#if defined(_KERNEL_OPT) +#include "opt_compat_netbsd.h" +#endif #include <sys/param.h> #include <sys/ioctl.h> @@ -46,13 +50,17 @@ __KERNEL_RCSID(0, "$NetBSD: rndpseudo.c, #include <sys/kernel.h> #include <sys/conf.h> #include <sys/systm.h> -#include <sys/rnd.h> #include <sys/vnode.h> #include <sys/pool.h> #include <sys/kauth.h> #include <sys/cprng.h> #include <sys/stat.h> +#include <sys/rnd.h> +#ifdef COMPAT_50 +#include <compat/sys/rnd.h> +#endif + #include <dev/rnd_private.h> #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */ @@ -428,7 +436,11 @@ rnd_ioctl(struct file *fp, u_long cmd, v break; default: - return (ENOTTY); +#ifdef COMPAT_50 + return compat_50_rnd_ioctl(fp, cmd, addr); +#else + return ENOTTY; +#endif } switch (cmd) { @@ -597,7 +609,7 @@ rnd_ioctl(struct file *fp, u_long cmd, v break; default: - return (ENOTTY); + return ENOTTY; } return (ret); Added files: Index: src/sys/compat/common/rndpseudo_50.c diff -u /dev/null src/sys/compat/common/rndpseudo_50.c:1.1 --- /dev/null Mon Dec 19 21:53:52 2011 +++ src/sys/compat/common/rndpseudo_50.c Mon Dec 19 21:53:52 2011 @@ -0,0 +1,182 @@ +/* $NetBSD: rndpseudo_50.c,v 1.1 2011/12/19 21:53:52 apb Exp $ */ + +/*- + * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Michael Graff <explo...@flame.org> and Thor Lancelot Simon. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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> +__KERNEL_RCSID(0, "$NetBSD: rndpseudo_50.c,v 1.1 2011/12/19 21:53:52 apb Exp $"); + +#if defined(_KERNEL_OPT) +#include "opt_compat_netbsd.h" +#include "opt_compat_netbsd32.h" +#endif + +#include <sys/param.h> +#include <sys/file.h> + +#include <sys/rnd.h> +#include <compat/sys/rnd.h> + +/* + * Convert from rndsource_t to rndsource50_t, for the results from + * RNDGETNUM50 and RNDGETNAME50. + */ +static void +rndsource_to_rndsource50(rndsource_t *r, rndsource50_t *r50) +{ + memset(r50, 0, sizeof(*r50)); + strlcpy(r50->name, r->name, sizeof(r50->name)); + r50->total = r->total; + r50->type = r->type; + r50->flags = r->flags; +} + +#ifdef COMPAT_NETBSD32 +/* + * Convert from rndsource_t to rndsource50_32_t, for the results from + * RNDGETNUM50_32 and RNDGETNAME50_32. + */ +static void +rndsource_to_rndsource50_32(rndsource_t *r, rndsource50_32_t *r50_32) +{ + memset(r50_32, 0, sizeof(*r50_32)); + strlcpy(r50_32->name, r->name, sizeof(r50_32->name)); + r50_32->total = r->total; + r50_32->type = r->type; + r50_32->flags = r->flags; +} +#endif /* COMPAT_NETBSD32 */ + +/* + * COMPAT_50 handling for rnd_ioctl. This is called from rnd_ioctl. + * + * It also handles the case of (COMPAT_50 && COMPAT_NETBSD32). + */ +int +compat_50_rnd_ioctl(struct file *fp, u_long cmd, void *addr) +{ + int ret = 0; + + switch (cmd) { + + case RNDGETSRCNUM50: + { + rndstat_t rstbuf = {.start = 0}; + rndstat50_t *rst50 = (rndstat50_t *)addr; + int count; + + if (rst50->count > RND_MAXSTATCOUNT50) + return EINVAL; + + rstbuf.start = rst50->start; + rstbuf.count = rst50->count; + + ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNUM, &rstbuf); + if (ret != 0) + return ret; + + for (count = 0; count < rst50->count; count++) { + rndsource_to_rndsource50(&rstbuf.source[count], + &rst50->source[count]); + } + rst50->count = rstbuf.count; + + break; + } + +#ifdef COMPAT_NETBSD32 + case RNDGETSRCNUM50_32: + { + rndstat_t rstbuf = {.start = 0}; + rndstat50_32_t *rst50_32 = (rndstat50_32_t *)addr; + int count; + + if (rst50_32->count > RND_MAXSTATCOUNT50) + return (EINVAL); + + rstbuf.start = rst50_32->start; + rstbuf.count = rst50_32->count; + + ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNUM, &rstbuf); + if (ret != 0) + return ret; + + for (count = 0; count < rst50_32->count; count++) { + rndsource_to_rndsource50_32(&rstbuf.source[count], + &rst50_32->source[count]); + } + rst50_32->count = rstbuf.count; + + break; + } +#endif /* COMPAT_NETBSD32 */ + + case RNDGETSRCNAME50: + { + rndstat_name_t rstnmbuf = {.name[0] = 0}; + rndstat_name50_t *rstnm50; + rstnm50 = (rndstat_name50_t *)addr; + + strlcpy(rstnmbuf.name, rstnm50->name, sizeof(rstnmbuf.name)); + + ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNAME, &rstnmbuf); + if (ret != 0) + return ret; + + rndsource_to_rndsource50(&rstnmbuf.source, &rstnm50->source); + + break; + } + +#ifdef COMPAT_NETBSD32 + case RNDGETSRCNAME50_32: + { + rndstat_name_t rstnmbuf = {.name[0] = 0}; + rndstat_name50_32_t *rstnm50_32; + rstnm50_32 = (rndstat_name50_32_t *)addr; + + strlcpy(rstnmbuf.name, rstnm50_32->name, sizeof(rstnmbuf.name)); + + ret = (fp->f_ops->fo_ioctl)(fp, RNDGETSRCNAME, &rstnmbuf); + if (ret != 0) + return ret; + + rndsource_to_rndsource50_32(&rstnmbuf.source, + &rstnm50_32->source); + + break; + } +#endif + + default: + return ENOTTY; + } + + return ret; +} Index: src/sys/compat/sys/rnd.h diff -u /dev/null src/sys/compat/sys/rnd.h:1.1 --- /dev/null Mon Dec 19 21:53:52 2011 +++ src/sys/compat/sys/rnd.h Mon Dec 19 21:53:52 2011 @@ -0,0 +1,154 @@ +/* $NetBSD: rnd.h,v 1.1 2011/12/19 21:53:52 apb Exp $ */ + +/*- + * Copyright (c) 1997,2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Michael Graff <explo...@flame.org>. This code uses ideas and + * algorithms from the Linux driver written by Ted Ts'o. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef _COMPAT_SYS_RND_H_ +#define _COMPAT_SYS_RND_H_ + +#if defined(_KERNEL_OPT) +#include "opt_compat_netbsd.h" +#include "opt_compat_netbsd32.h" +#endif + +#include <sys/types.h> +#include <sys/ioctl.h> + +#ifdef COMPAT_NETBSD32 +#include <compat/netbsd32/netbsd32.h> +#endif /* COMPAT_NETBSD32 */ + +#include <sys/rnd.h> + +#ifdef COMPAT_50 + +/* + * NetBSD-5 used "void *state" in the rndsource_t struct. rndsource_t + * was used in rnstat_t and rnstat_name_t, which were used by + * the NetBSD-5 RNDGETSRCNUM and RNDGETSRCNAME ioctls. + * + */ + +/* Sanitized random source view for userspace. */ +typedef struct { + char name[16]; /* device name */ + uint32_t unused_time; /* was: last time recorded */ + uint32_t unused_delta; /* was: last delta value */ + uint32_t unused_delta2; /* was: last delta2 value */ + uint32_t total; /* entropy from this source */ + uint32_t type; /* type */ + uint32_t flags; /* flags */ + void *unused_state; /* was: internal state */ +} rndsource50_t; + +#ifdef COMPAT_NETBSD32 +typedef struct { + char name[16]; /* device name */ + uint32_t unused_time; /* was: last time recorded */ + uint32_t unused_delta; /* was: last delta value */ + uint32_t unused_delta2; /* was: last delta2 value */ + uint32_t total; /* entropy from this source */ + uint32_t type; /* type */ + uint32_t flags; /* flags */ + netbsd32_voidp unused_state; /* was: internal state */ +} rndsource50_32_t; +#endif /* COMPAT_NETBSD32 */ + +/* + * NetBSD-5 defined RND_MAXSTATCOUNT as 10. We define RND_MAXSTATCOUNT50 + * here, and check that the native RND_MAXSTATCOUNT is not smaller. + */ +#define RND_MAXSTATCOUNT50 10 /* 10 sources at once max */ +#if (RND_MAXSTATCOUNT50 > RND_MAXSTATCOUNT) + #error "RND_MAXSTATCOUNT50 is too large" +#endif + +/* + * return "count" random entries, starting at "start" + */ +typedef struct { + uint32_t start; + uint32_t count; + rndsource50_t source[RND_MAXSTATCOUNT50]; +} rndstat50_t; + +#ifdef COMPAT_NETBSD32 +typedef struct { + uint32_t start; + uint32_t count; + rndsource50_32_t source[RND_MAXSTATCOUNT50]; +} rndstat50_32_t; +#endif /* COMPAT_NETBSD32 */ + +/* + * return information on a specific source by name + */ +typedef struct { + char name[16]; + rndsource50_t source; +} rndstat_name50_t; + +#ifdef COMPAT_NETBSD32 +typedef struct { + char name[16]; + rndsource50_32_t source; +} rndstat_name50_32_t; +#endif /* COMPAT_NETBSD32 */ + +/* + * NetBSD-5 defined RND_POOLWORDS as 128. In NetBSD-6, the value + * exposed to userland via the rnddata_t type was renamed to + * RND_SAVEWORDS. As long as RND_SAVEWORDS remains equal to 128, then + * rnddata_t (used by ioctl RNDADDATA), and rndpoolstat_t (used by ioctl + * RNDGETPOOLSTAT) remain ABI compatible without any extra effort, even + * though the declarations in the source code have changed. + */ +#if (RND_SAVEWORDS != 128) + #error "RND_SAVEWORDS must be 128 for NetBSD-5 compatibility" +#endif + +/* + * Compatibility with NetBSD-5 ioctls. + */ +#ifdef _KERNEL +int compat_50_rnd_ioctl(struct file *, u_long, void *); +#endif + +#define RNDGETSRCNUM50 _IOWR('R', 102, rndstat50_t) +#define RNDGETSRCNAME50 _IOWR('R', 103, rndstat_name50_t) + +#ifdef COMPAT_NETBSD32 +#define RNDGETSRCNUM50_32 _IOWR('R', 102, rndstat50_32_t) +#define RNDGETSRCNAME50_32 _IOWR('R', 103, rndstat_name50_32_t) +#endif /* COMPAT_NETBSD32 */ + +#endif /* COMPAT_50 */ + +#endif /* !_COMPAT_SYS_RND_H_ */