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_ */

Reply via email to