Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Make struct disklabel 8 byte aligned. This increases it...
details: https://anonhg.NetBSD.org/src/rev/97eb78964585
branches: trunk
changeset: 761009:97eb78964585
user: matt <matt%NetBSD.org@localhost>
date: Tue Jan 18 19:52:23 2011 +0000
description:
Make struct disklabel 8 byte aligned. This increases its size by 4 bytes
on IPL32 platforms so add code in sys_ioctl (and netbsd32_ioctl) to deal
with the older/smaller diskabel size. This change makes disklabel the
same for both IPL32 and LP64 platforms.
diffstat:
sys/compat/netbsd32/netbsd32_ioctl.c | 119 ++++++++++++++++++++++++----------
sys/kern/sys_generic.c | 51 ++++++++++++--
sys/sys/disklabel.h | 3 +-
sys/sys/dkio.h | 3 +-
4 files changed, 127 insertions(+), 49 deletions(-)
diffs (truncated from 327 to 300 lines):
diff -r c5955f837b22 -r 97eb78964585 sys/compat/netbsd32/netbsd32_ioctl.c
--- a/sys/compat/netbsd32/netbsd32_ioctl.c Tue Jan 18 19:41:02 2011 +0000
+++ b/sys/compat/netbsd32/netbsd32_ioctl.c Tue Jan 18 19:52:23 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_ioctl.c,v 1.51 2010/09/24 13:12:53 njoly Exp $ */
+/* $NetBSD: netbsd32_ioctl.c,v 1.52 2011/01/18 19:52:24 matt Exp $ */
/*
* Copyright (c) 1998, 2001 Matthew R. Green
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.51 2010/09/24 13:12:53 njoly Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.52 2011/01/18 19:52:24 matt Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -437,10 +437,11 @@
struct filedesc *fdp;
u_long com;
int error = 0;
- u_int size, size32;
+ size_t size;
+ size_t alloc_size32, size32;
void *data, *memp = NULL;
void *data32, *memp32 = NULL;
- unsigned fd;
+ unsigned int fd;
fdfile_t *ff;
int tmp;
#define STK_PARAMS 128
@@ -453,17 +454,26 @@
*/
#if 0
{
-char *dirs[8] = { "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!",
- "INOUT", "VOID|IN|OUT!" };
+ const char * const dirs[8] = {
+ "NONE!", "VOID", "OUT", "VOID|OUT!", "IN", "VOID|IN!",
+ "INOUT", "VOID|IN|OUT!"
+ };
-printf("netbsd32_ioctl(%d, %x, %x): %s group %c base %d len %d\n",
- SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data),
- dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)],
- IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)),
- IOCPARM_LEN(SCARG(uap, com)));
+ printf("netbsd32_ioctl(%d, %x, %x): "
+ "%s group %c base %d len %d\n",
+ SCARG(uap, fd), SCARG(uap, com), SCARG(uap, data).i32,
+ dirs[((SCARG(uap, com) & IOC_DIRMASK)>>29)],
+ IOCGROUP(SCARG(uap, com)), IOCBASECMD(SCARG(uap, com)),
+ IOCPARM_LEN(SCARG(uap, com)));
}
#endif
+ memp = NULL;
+ memp32 = NULL;
+ alloc_size32 = 0;
+ size32 = 0;
+ size = 0;
+
fdp = p->p_fd;
fd = SCARG(uap, fd);
if ((fp = fd_getfile(fd)) == NULL)
@@ -489,37 +499,72 @@
* Interpret high order word to find amount of data to be
* copied to/from the user's address space.
*/
- size = 0;
size32 = IOCPARM_LEN(com);
- if (size32 > IOCPARM_MAX) {
+ alloc_size32 = size32;
+
+ /*
+ * The disklabel is now padded to a multiple of 8 bytes however the old
+ * disklabel on 32bit platforms wasn't. This leaves a difference in
+ * size of 4 bytes between the two but are otherwise identical.
+ * To deal with this, we allocate enough space for the new disklabel
+ * but only copyin/out the smaller amount.
+ */
+ if (IOCGROUP(com) == 'd') {
+ u_long ncom = com ^ (DIOCGDINFO ^ DIOCGDINFO32);
+ switch (ncom) {
+ case DIOCGDINFO:
+ case DIOCWDINFO:
+ case DIOCSDINFO:
+ case DIOCGDEFLABEL:
+ com = ncom;
+ if (IOCPARM_LEN(DIOCGDINFO32) < IOCPARM_LEN(DIOCGDINFO))
+ alloc_size32 = IOCPARM_LEN(DIOCGDINFO);
+ break;
+ }
+ }
+ if (alloc_size32 > IOCPARM_MAX) {
error = ENOTTY;
goto out;
}
- if (size32 > sizeof(stkbuf)) {
- memp32 = kmem_alloc((size_t)size32, KM_SLEEP);
+ if (alloc_size32 > sizeof(stkbuf)) {
+ memp32 = kmem_alloc(alloc_size32, KM_SLEEP);
data32 = memp32;
} else
data32 = (void *)stkbuf32;
- if (com&IOC_IN) {
- if (size32) {
- error = copyin(SCARG_P32(uap, data), data32, size32);
- if (error) {
- if (memp32)
- kmem_free(memp32, (size_t)size32);
- goto out;
- }
- ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data),
- size32, 0);
- } else
+ if ((com >> IOCPARM_SHIFT) == 0) {
+ /* UNIX-style ioctl. */
+ data32 = SCARG_P32(uap, data);
+ } else {
+ if (com&IOC_IN) {
+ if (size32) {
+ error = copyin(SCARG_P32(uap, data), data32,
+ size32);
+ if (error) {
+ goto out;
+ }
+ /*
+ * The data between size and alloc_size has
+ * not been overwritten. It shouldn't matter
+ * but let's clear that anyway.
+ */
+ if (__predict_false(size32 < alloc_size32)) {
+ memset((char *)data32+size32, 0,
+ alloc_size32 - size32);
+ }
+ ktrgenio(fd, UIO_WRITE, SCARG_P32(uap, data),
+ size32, 0);
+ } else
+ *(void **)data32 = SCARG_P32(uap, data);
+ } else if ((com&IOC_OUT) && size32) {
+ /*
+ * Zero the buffer so the user always
+ * gets back something deterministic.
+ */
+ memset(data32, 0, alloc_size32);
+ } else if (com&IOC_VOID) {
*(void **)data32 = SCARG_P32(uap, data);
- } else if ((com&IOC_OUT) && size32)
- /*
- * Zero the buffer so the user always
- * gets back something deterministic.
- */
- memset(data32, 0, size32);
- else if (com&IOC_VOID)
- *(void **)data32 = SCARG_P32(uap, data);
+ }
+ }
/*
* convert various structures, pointers, and other objects that
@@ -690,12 +735,12 @@
size32, error);
}
+ out:
/* If we allocated data, free it here. */
if (memp32)
- kmem_free(memp32, (size_t)size32);
+ kmem_free(memp32, alloc_size32);
if (memp)
- kmem_free(memp, (size_t)size);
- out:
+ kmem_free(memp32, size);
fd_putfile(fd);
return (error);
}
diff -r c5955f837b22 -r 97eb78964585 sys/kern/sys_generic.c
--- a/sys/kern/sys_generic.c Tue Jan 18 19:41:02 2011 +0000
+++ b/sys/kern/sys_generic.c Tue Jan 18 19:52:23 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_generic.c,v 1.124 2009/08/13 08:57:43 haad Exp $ */
+/* $NetBSD: sys_generic.c,v 1.125 2011/01/18 19:52:23 matt Exp $ */
/*-
* Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.124 2009/08/13 08:57:43 haad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.125 2011/01/18 19:52:23 matt Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -90,6 +90,7 @@
#include <sys/syscallargs.h>
#include <sys/ktrace.h>
#include <sys/atomic.h>
+#include <sys/disklabel.h>
#include <uvm/uvm_extern.h>
@@ -524,12 +525,14 @@
struct filedesc *fdp;
u_long com;
int error;
- u_int size;
+ size_t size, alloc_size;
void *data, *memp;
#define STK_PARAMS 128
u_long stkbuf[STK_PARAMS/sizeof(u_long)];
fdfile_t *ff;
+ memp = NULL;
+ alloc_size = 0;
error = 0;
p = l->l_proc;
fdp = p->p_fd;
@@ -560,6 +563,28 @@
* copied to/from the user's address space.
*/
size = IOCPARM_LEN(com);
+ alloc_size = size;
+
+ /*
+ * The disklabel is now padded to a multiple of 8 bytes however the old
+ * disklabel on 32bit platforms wasn't. This leaves a difference in
+ * size of 4 bytes between the two but are otherwise identical.
+ * To deal with this, we allocate enough space for the new disklabel
+ * but only copyin/out the smaller amount.
+ */
+ if (IOCGROUP(com) == 'd') {
+ u_long ncom = com ^ (DIOCGDINFO ^ DIOCGDINFO32);
+ switch (ncom) {
+ case DIOCGDINFO:
+ case DIOCWDINFO:
+ case DIOCSDINFO:
+ case DIOCGDEFLABEL:
+ com = ncom;
+ if (IOCPARM_LEN(DIOCGDINFO32) < IOCPARM_LEN(DIOCGDINFO))
+ alloc_size = IOCPARM_LEN(DIOCGDINFO);
+ break;
+ }
+ }
if (size > IOCPARM_MAX) {
error = ENOTTY;
goto out;
@@ -569,8 +594,8 @@
/* UNIX-style ioctl. */
data = SCARG(uap, data);
} else {
- if (size > sizeof(stkbuf)) {
- memp = kmem_alloc(size, KM_SLEEP);
+ if (alloc_size > sizeof(stkbuf)) {
+ memp = kmem_alloc(alloc_size, KM_SLEEP);
data = memp;
} else {
data = (void *)stkbuf;
@@ -579,11 +604,17 @@
if (size) {
error = copyin(SCARG(uap, data), data, size);
if (error) {
- if (memp) {
- kmem_free(memp, size);
- }
goto out;
}
+ /*
+ * The data between size and alloc_size has
+ * not been overwritten. It shouldn't matter
+ * but let's clear that anyway.
+ */
+ if (__predict_false(size < alloc_size)) {
+ memset((char *)data+size, 0,
+ alloc_size - size);
+ }
ktrgenio(SCARG(uap, fd), UIO_WRITE,
SCARG(uap, data), size, 0);
} else {
@@ -633,9 +664,9 @@
}
break;
}
+ out:
if (memp)
- kmem_free(memp, size);
- out:
+ kmem_free(memp, alloc_size);
fd_putfile(SCARG(uap, fd));
switch (error) {
case -1:
diff -r c5955f837b22 -r 97eb78964585 sys/sys/disklabel.h
--- a/sys/sys/disklabel.h Tue Jan 18 19:41:02 2011 +0000
+++ b/sys/sys/disklabel.h Tue Jan 18 19:52:23 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: disklabel.h,v 1.107 2009/12/22 18:55:25 pooka Exp $ */
+/* $NetBSD: disklabel.h,v 1.108 2011/01/18 19:52:24 matt Exp $ */
Home |
Main Index |
Thread Index |
Old Index